163 if (mX == 0.0 && mY == 0.0)
return;
164 const double lenInv = 1.0/
length();
178 if (mX == 0.0 && mY == 0.0)
return *
this;
179 const double lenInv = 1.0/
length();
194 if (!qFuzzyIsNull(vLengthSqr))
196 const double mu = v.
dot(*
this-start)/vLengthSqr;
198 return (*
this-start).lengthSquared();
200 return (*
this-end).lengthSquared();
202 return ((start + mu*v)-*
this).lengthSquared();
204 return (*
this-start).lengthSquared();
299 mIsAntialiasing(false)
314 mIsAntialiasing(false)
316 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) // before Qt5, default pens used to be cosmetic if NonCosmeticDefaultPen flag isn't set. So we set it to get consistency across Qt versions.
318 setRenderHint(QPainter::NonCosmeticDefaultPen);
330 QPainter::setPen(pen);
344 QPainter::setPen(
color);
358 QPainter::setPen(penStyle);
374 QPainter::drawLine(line);
376 QPainter::drawLine(line.toLine());
387 setRenderHint(QPainter::Antialiasing, enabled);
396 translate(-0.5, -0.5);
423 bool result = QPainter::begin(device);
424 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) // before Qt5, default pens used to be cosmetic if NonCosmeticDefaultPen flag isn't set. So we set it to get consistency across Qt versions.
426 setRenderHint(QPainter::NonCosmeticDefaultPen);
438 if (!enabled &&
mModes.testFlag(mode))
440 else if (enabled && !
mModes.testFlag(mode))
471 qDebug() << Q_FUNC_INFO <<
"Unbalanced save/restore";
481 if (qFuzzyIsNull(pen().widthF()))
583 mDevicePixelRatio(devicePixelRatio),
642 #ifdef QCP_DEVICEPIXELRATIO_SUPPORTED
646 qDebug() << Q_FUNC_INFO <<
"Device pixel ratios not supported for Qt versions before 5.4";
681 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
682 result->setRenderHint(QPainter::HighQualityAntialiasing);
690 if (painter && painter->isActive())
691 painter->drawPixmap(0, 0,
mBuffer);
693 qDebug() << Q_FUNC_INFO <<
"invalid or inactive painter passed";
708 #ifdef QCP_DEVICEPIXELRATIO_SUPPORTED
712 qDebug() << Q_FUNC_INFO <<
"Device pixel ratios not supported for Qt versions before 5.4";
723 #ifdef QCP_OPENGL_PBUFFER
747 QCPPaintBufferGlPbuffer::QCPPaintBufferGlPbuffer(
const QSize &size,
double devicePixelRatio,
int multisamples) :
750 mMultisamples(qMax(0, multisamples))
752 QCPPaintBufferGlPbuffer::reallocateBuffer();
755 QCPPaintBufferGlPbuffer::~QCPPaintBufferGlPbuffer()
762 QCPPainter *QCPPaintBufferGlPbuffer::startPainting()
764 if (!mGlPBuffer->isValid())
766 qDebug() << Q_FUNC_INFO <<
"OpenGL frame buffer object doesn't exist, reallocateBuffer was not called?";
771 result->setRenderHint(QPainter::HighQualityAntialiasing);
776 void QCPPaintBufferGlPbuffer::draw(
QCPPainter *painter)
const
778 if (!painter || !painter->isActive())
780 qDebug() << Q_FUNC_INFO <<
"invalid or inactive painter passed";
783 if (!mGlPBuffer->isValid())
785 qDebug() << Q_FUNC_INFO <<
"OpenGL pbuffer isn't valid, reallocateBuffer was not called?";
788 painter->drawImage(0, 0, mGlPBuffer->toImage());
792 void QCPPaintBufferGlPbuffer::clear(
const QColor &
color)
794 if (mGlPBuffer->isValid())
796 mGlPBuffer->makeCurrent();
798 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
799 mGlPBuffer->doneCurrent();
801 qDebug() << Q_FUNC_INFO <<
"OpenGL pbuffer invalid or context not current";
805 void QCPPaintBufferGlPbuffer::reallocateBuffer()
811 format.setAlpha(
true);
812 format.setSamples(mMultisamples);
813 mGlPBuffer =
new QGLPixelBuffer(mSize, format);
815 #endif // QCP_OPENGL_PBUFFER
818 #ifdef QCP_OPENGL_FBO
843 QCPPaintBufferGlFbo::QCPPaintBufferGlFbo(
const QSize &size,
double devicePixelRatio, QWeakPointer<QOpenGLContext> glContext, QWeakPointer<QOpenGLPaintDevice> glPaintDevice) :
845 mGlContext(glContext),
846 mGlPaintDevice(glPaintDevice),
849 QCPPaintBufferGlFbo::reallocateBuffer();
852 QCPPaintBufferGlFbo::~QCPPaintBufferGlFbo()
855 delete mGlFrameBuffer;
859 QCPPainter *QCPPaintBufferGlFbo::startPainting()
861 QSharedPointer<QOpenGLPaintDevice> paintDevice = mGlPaintDevice.toStrongRef();
862 QSharedPointer<QOpenGLContext> context = mGlContext.toStrongRef();
865 qDebug() << Q_FUNC_INFO <<
"OpenGL paint device doesn't exist";
870 qDebug() << Q_FUNC_INFO <<
"OpenGL context doesn't exist";
875 qDebug() << Q_FUNC_INFO <<
"OpenGL frame buffer object doesn't exist, reallocateBuffer was not called?";
879 if (QOpenGLContext::currentContext() != context.data())
880 context->makeCurrent(context->surface());
881 mGlFrameBuffer->bind();
883 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
884 result->setRenderHint(QPainter::HighQualityAntialiasing);
890 void QCPPaintBufferGlFbo::donePainting()
892 if (mGlFrameBuffer && mGlFrameBuffer->isBound())
893 mGlFrameBuffer->release();
895 qDebug() << Q_FUNC_INFO <<
"Either OpenGL frame buffer not valid or was not bound";
899 void QCPPaintBufferGlFbo::draw(
QCPPainter *painter)
const
901 if (!painter || !painter->isActive())
903 qDebug() << Q_FUNC_INFO <<
"invalid or inactive painter passed";
908 qDebug() << Q_FUNC_INFO <<
"OpenGL frame buffer object doesn't exist, reallocateBuffer was not called?";
911 painter->drawImage(0, 0, mGlFrameBuffer->toImage());
915 void QCPPaintBufferGlFbo::clear(
const QColor &
color)
917 QSharedPointer<QOpenGLContext> context = mGlContext.toStrongRef();
920 qDebug() << Q_FUNC_INFO <<
"OpenGL context doesn't exist";
925 qDebug() << Q_FUNC_INFO <<
"OpenGL frame buffer object doesn't exist, reallocateBuffer was not called?";
929 if (QOpenGLContext::currentContext() != context.data())
930 context->makeCurrent(context->surface());
931 mGlFrameBuffer->bind();
933 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
934 mGlFrameBuffer->release();
938 void QCPPaintBufferGlFbo::reallocateBuffer()
943 if (mGlFrameBuffer->isBound())
944 mGlFrameBuffer->release();
945 delete mGlFrameBuffer;
949 QSharedPointer<QOpenGLPaintDevice> paintDevice = mGlPaintDevice.toStrongRef();
950 QSharedPointer<QOpenGLContext> context = mGlContext.toStrongRef();
953 qDebug() << Q_FUNC_INFO <<
"OpenGL paint device doesn't exist";
958 qDebug() << Q_FUNC_INFO <<
"OpenGL context doesn't exist";
963 context->makeCurrent(context->surface());
964 QOpenGLFramebufferObjectFormat frameBufferFormat;
965 frameBufferFormat.setSamples(context->format().samples());
966 frameBufferFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
967 mGlFrameBuffer =
new QOpenGLFramebufferObject(mSize*mDevicePixelRatio, frameBufferFormat);
968 if (paintDevice->size() != mSize*mDevicePixelRatio)
969 paintDevice->setSize(mSize*mDevicePixelRatio);
970 #ifdef QCP_DEVICEPIXELRATIO_SUPPORTED
971 paintDevice->setDevicePixelRatio(mDevicePixelRatio);
974 #endif // QCP_OPENGL_FBO
1068 QObject(parentPlot),
1069 mParentPlot(parentPlot),
1090 qDebug() << Q_FUNC_INFO <<
"The parent plot's mCurrentLayer will be a dangling pointer. Should have been set to a valid layer or nullptr beforehand.";
1132 if (QSharedPointer<QCPAbstractPaintBuffer> pb =
mPaintBuffer.toStrongRef())
1133 pb->setInvalidated();
1150 painter->setClipRect(child->
clipRect().translated(0, -1));
1152 child->
draw(painter);
1168 if (QSharedPointer<QCPAbstractPaintBuffer> pb =
mPaintBuffer.toStrongRef())
1170 if (
QCPPainter *painter = pb->startPainting())
1172 if (painter->isActive())
1175 qDebug() << Q_FUNC_INFO <<
"paint buffer returned inactive painter";
1179 qDebug() << Q_FUNC_INFO <<
"paint buffer returned nullptr painter";
1181 qDebug() << Q_FUNC_INFO <<
"no valid paint buffer associated with this layer";
1202 if (QSharedPointer<QCPAbstractPaintBuffer> pb =
mPaintBuffer.toStrongRef())
1204 pb->clear(Qt::transparent);
1206 pb->setInvalidated(
false);
1209 qDebug() << Q_FUNC_INFO <<
"no valid paint buffer associated with this layer";
1232 if (QSharedPointer<QCPAbstractPaintBuffer> pb =
mPaintBuffer.toStrongRef())
1233 pb->setInvalidated();
1235 qDebug() << Q_FUNC_INFO <<
"layerable is already child of this layer" <<
reinterpret_cast<quintptr
>(layerable);
1251 if (QSharedPointer<QCPAbstractPaintBuffer> pb =
mPaintBuffer.toStrongRef())
1252 pb->setInvalidated();
1254 qDebug() << Q_FUNC_INFO <<
"layerable is not child of this layer" <<
reinterpret_cast<quintptr
>(layerable);
1370 mParentLayerable(parentLayerable),
1376 if (targetLayer.isEmpty())
1379 qDebug() << Q_FUNC_INFO <<
"setting QCPlayerable initial layer to" << targetLayer <<
"failed.";
1425 qDebug() << Q_FUNC_INFO <<
"no parent QCustomPlot set";
1433 qDebug() << Q_FUNC_INFO <<
"there is no layer with name" << layerName;
1506 Q_UNUSED(onlySelectable)
1532 qDebug() << Q_FUNC_INFO <<
"called with mParentPlot already initialized";
1537 qDebug() << Q_FUNC_INFO <<
"called with parentPlot zero";
1571 qDebug() << Q_FUNC_INFO <<
"no parent QCustomPlot set";
1576 qDebug() << Q_FUNC_INFO <<
"layer" <<
layer->
name() <<
"is not in same QCustomPlot as this layerable";
1695 Q_UNUSED(selectionStateChanged)
1712 Q_UNUSED(selectionStateChanged)
1982 lower = includeCoord;
1984 upper = includeCoord;
2001 result.
expand(otherRange);
2018 result.
expand(includeCoord);
2032 if (lowerBound > upperBound)
2033 qSwap(lowerBound, upperBound);
2036 if (result.
lower < lowerBound)
2038 result.
lower = lowerBound;
2040 if (result.
upper > upperBound || qFuzzyCompare(
size(), upperBound-lowerBound))
2041 result.
upper = upperBound;
2042 }
else if (result.
upper > upperBound)
2044 result.
upper = upperBound;
2046 if (result.
lower < lowerBound || qFuzzyCompare(
size(), upperBound-lowerBound))
2047 result.
lower = lowerBound;
2067 double rangeFac = 1e-3;
2072 if (sanitizedRange.
lower == 0.0 && sanitizedRange.
upper != 0.0)
2075 if (rangeFac < sanitizedRange.
upper*rangeFac)
2076 sanitizedRange.
lower = rangeFac;
2078 sanitizedRange.
lower = sanitizedRange.
upper*rangeFac;
2080 else if (sanitizedRange.
lower != 0.0 && sanitizedRange.
upper == 0.0)
2083 if (-rangeFac > sanitizedRange.
lower*rangeFac)
2084 sanitizedRange.
upper = -rangeFac;
2086 sanitizedRange.
upper = sanitizedRange.
lower*rangeFac;
2087 }
else if (sanitizedRange.
lower < 0 && sanitizedRange.
upper > 0)
2090 if (-sanitizedRange.
lower > sanitizedRange.
upper)
2093 if (-rangeFac > sanitizedRange.
lower*rangeFac)
2094 sanitizedRange.
upper = -rangeFac;
2096 sanitizedRange.
upper = sanitizedRange.
lower*rangeFac;
2100 if (rangeFac < sanitizedRange.
upper*rangeFac)
2101 sanitizedRange.
lower = rangeFac;
2103 sanitizedRange.
lower = sanitizedRange.
upper*rangeFac;
2107 return sanitizedRange;
2118 return sanitizedRange;
2288 if (mEnd <= other.mBegin)
2301 return {qMin(mBegin, other.mBegin), qMax(mEnd, other.mEnd)};
2316 QCPDataRange result(qMax(mBegin, other.mBegin), qMin(mEnd, other.mEnd));
2330 return !( (mBegin > other.mBegin && mBegin >= other.mEnd) ||
2331 (mEnd <= other.mBegin && mEnd < other.mEnd) );
2341 return mBegin <= other.mBegin && mEnd >= other.mEnd;
2424 mDataRanges.append(range);
2436 if (mDataRanges.size() != other.mDataRanges.size())
2438 for (
int i=0; i<mDataRanges.size(); ++i)
2440 if (mDataRanges.at(i) != other.mDataRanges.at(i))
2452 mDataRanges << other.mDataRanges;
2488 while (i < mDataRanges.size())
2490 const int thisBegin = mDataRanges.at(i).begin();
2491 const int thisEnd = mDataRanges.at(i).end();
2492 if (thisBegin >= other.
end())
2495 if (thisEnd > other.
begin())
2497 if (thisBegin >= other.
begin())
2499 if (thisEnd <= other.
end())
2501 mDataRanges.removeAt(i);
2504 mDataRanges[i].setBegin(other.
end());
2507 if (thisEnd <= other.
end())
2509 mDataRanges[i].setEnd(other.
begin());
2512 mDataRanges[i].setEnd(other.
begin());
2546 if (index >= 0 && index < mDataRanges.size())
2548 return mDataRanges.at(index);
2551 qDebug() << Q_FUNC_INFO <<
"index out of range:" << index;
2565 return {mDataRanges.first().begin(), mDataRanges.last().end()};
2588 mDataRanges.clear();
2603 for (
int i=mDataRanges.size()-1; i>=0; --i)
2605 if (mDataRanges.at(i).isEmpty())
2606 mDataRanges.removeAt(i);
2608 if (mDataRanges.isEmpty())
2612 std::sort(mDataRanges.begin(), mDataRanges.end(), lessThanDataRangeBegin);
2616 while (i < mDataRanges.size())
2618 if (mDataRanges.at(i-1).end() >= mDataRanges.at(i).begin())
2620 mDataRanges[i-1].setEnd(qMax(mDataRanges.at(i-1).end(), mDataRanges.at(i).end()));
2621 mDataRanges.removeAt(i);
2644 mDataRanges.clear();
2655 if (!mDataRanges.isEmpty())
2657 if (mDataRanges.size() > 1)
2658 mDataRanges = QList<QCPDataRange>() << mDataRanges.first();
2659 if (mDataRanges.first().length() > 1)
2660 mDataRanges.first().setEnd(mDataRanges.first().begin()+1);
2667 mDataRanges = QList<QCPDataRange>() <<
span();
2686 if (other.
isEmpty())
return false;
2690 while (thisIndex < mDataRanges.size() && otherIndex < other.mDataRanges.size())
2692 if (mDataRanges.at(thisIndex).contains(other.mDataRanges.at(otherIndex)))
2697 return thisIndex < mDataRanges.size();
2747 if (mDataRanges.first().begin() != fullRange.
begin())
2750 for (
int i=1; i<mDataRanges.size(); ++i)
2753 if (mDataRanges.last().end() != fullRange.
end())
2848 mPen(QBrush(Qt::gray), 0, Qt::DashLine),
2849 mBrush(Qt::NoBrush),
2873 qDebug() << Q_FUNC_INFO <<
"called with axis zero";
2921 mRect = QRect(event->pos(), event->pos());
2933 mRect.setBottomRight(event->pos());
2946 mRect.setBottomRight(event->pos());
2959 if (event->key() == Qt::Key_Escape &&
mActive)
2983 painter->setBrush(
mBrush);
2984 painter->drawRect(
mRect);
3042 QObject(parentPlot),
3043 mParentPlot(parentPlot)
3062 QHashIterator<QCP::MarginSide, QList<QCPLayoutElement*> > it(
mChildren);
3063 while (it.hasNext())
3066 if (!it.value().isEmpty())
3079 QHashIterator<QCP::MarginSide, QList<QCPLayoutElement*> > it(
mChildren);
3080 while (it.hasNext())
3083 const QList<QCPLayoutElement*>
elements = it.value();
3084 for (
int i=
elements.size()-1; i>=0; --i)
3085 elements.at(i)->setMarginGroup(it.key(),
nullptr);
3125 qDebug() << Q_FUNC_INFO <<
"element is already child of this margin group side" <<
reinterpret_cast<quintptr
>(element);
3136 if (!
mChildren[side].removeOne(element))
3137 qDebug() << Q_FUNC_INFO <<
"element is not child of this margin group side" <<
reinterpret_cast<quintptr
>(element);
3209 mParentLayout(nullptr),
3211 mMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX),
3212 mSizeConstraintRect(scrInnerRect),
3214 mOuterRect(0, 0, 0, 0),
3215 mMargins(0, 0, 0, 0),
3216 mMinimumMargins(0, 0, 0, 0),
3398 QVector<QCP::MarginSide> sideVector;
3498 return {QWIDGETSIZE_MAX, QWIDGETSIZE_MAX};
3511 return QList<QCPLayoutElement*>();
3538 qDebug() << Q_FUNC_INFO <<
"parent plot not defined";
3689 for (
int i=0; i<elCount; ++i)
3700 QList<QCPLayoutElement*> result;
3701 #if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
3704 for (
int i=0; i<c; ++i)
3708 for (
int i=0; i<c; ++i)
3711 result << result.at(i)->elements(recursive);
3796 if (QWidget *w = qobject_cast<QWidget*>(parent()))
3797 w->updateGeometry();
3798 else if (
QCPLayout *l = qobject_cast<QCPLayout*>(parent()))
3799 l->sizeConstraintsChanged();
3837 el->setParent(
this);
3842 qDebug() << Q_FUNC_INFO <<
"Null element passed";
3864 qDebug() << Q_FUNC_INFO <<
"Null element passed";
3898 if (maxSizes.size() != minSizes.size() || minSizes.size() != stretchFactors.size())
3900 qDebug() << Q_FUNC_INFO <<
"Passed vector sizes aren't equal:" << maxSizes << minSizes << stretchFactors;
3901 return QVector<int>();
3903 if (stretchFactors.isEmpty())
3904 return QVector<int>();
3905 int sectionCount = stretchFactors.size();
3906 QVector<double> sectionSizes(sectionCount);
3909 for (
int i=0; i<sectionCount; ++i)
3910 minSizeSum += minSizes.at(i);
3911 if (totalSize < minSizeSum)
3914 for (
int i=0; i<sectionCount; ++i)
3916 stretchFactors[i] = minSizes.at(i);
3921 QList<int> minimumLockedSections;
3922 QList<int> unfinishedSections;
3923 for (
int i=0; i<sectionCount; ++i)
3924 unfinishedSections.append(i);
3925 double freeSize = totalSize;
3927 int outerIterations = 0;
3928 while (!unfinishedSections.isEmpty() && outerIterations < sectionCount*2)
3931 int innerIterations = 0;
3932 while (!unfinishedSections.isEmpty() && innerIterations < sectionCount*2)
3937 double nextMax = 1e12;
3938 foreach (
int secId, unfinishedSections)
3940 double hitsMaxAt = (maxSizes.at(secId)-sectionSizes.at(secId))/stretchFactors.at(secId);
3941 if (hitsMaxAt < nextMax)
3943 nextMax = hitsMaxAt;
3949 double stretchFactorSum = 0;
3950 foreach (
int secId, unfinishedSections)
3951 stretchFactorSum += stretchFactors.at(secId);
3952 double nextMaxLimit = freeSize/stretchFactorSum;
3953 if (nextMax < nextMaxLimit)
3955 foreach (
int secId, unfinishedSections)
3957 sectionSizes[secId] += nextMax*stretchFactors.at(secId);
3958 freeSize -= nextMax*stretchFactors.at(secId);
3960 unfinishedSections.removeOne(nextId);
3963 foreach (
int secId, unfinishedSections)
3964 sectionSizes[secId] += nextMaxLimit*stretchFactors.at(secId);
3965 unfinishedSections.clear();
3968 if (innerIterations == sectionCount*2)
3969 qDebug() << Q_FUNC_INFO <<
"Exceeded maximum expected inner iteration count, layouting aborted. Input was:" << maxSizes << minSizes << stretchFactors << totalSize;
3972 bool foundMinimumViolation =
false;
3973 for (
int i=0; i<sectionSizes.size(); ++i)
3975 if (minimumLockedSections.contains(i))
3977 if (sectionSizes.at(i) < minSizes.at(i))
3979 sectionSizes[i] = minSizes.at(i);
3980 foundMinimumViolation =
true;
3981 minimumLockedSections.append(i);
3984 if (foundMinimumViolation)
3986 freeSize = totalSize;
3987 for (
int i=0; i<sectionCount; ++i)
3989 if (!minimumLockedSections.contains(i))
3990 unfinishedSections.append(i);
3992 freeSize -= sectionSizes.at(i);
3995 foreach (
int secId, unfinishedSections)
3996 sectionSizes[secId] = 0;
3999 if (outerIterations == sectionCount*2)
4000 qDebug() << Q_FUNC_INFO <<
"Exceeded maximum expected outer iteration count, layouting aborted. Input was:" << maxSizes << minSizes << stretchFactors << totalSize;
4002 QVector<int> result(sectionCount);
4003 for (
int i=0; i<sectionCount; ++i)
4004 result[i] = qRound(sectionSizes.at(i));
4025 minOuter.rwidth() += el->
margins().left() + el->
margins().right();
4027 minOuter.rheight() += el->
margins().top() + el->
margins().bottom();
4029 return {minOuter.width() > 0 ? minOuter.width() : minOuterHint.width(),
4030 minOuter.height() > 0 ? minOuter.height() : minOuterHint.height()};
4050 maxOuter.rwidth() += el->
margins().left() + el->
margins().right();
4052 maxOuter.rheight() += el->
margins().top() + el->
margins().bottom();
4054 return {maxOuter.width() < QWIDGETSIZE_MAX ? maxOuter.width() : maxOuterHint.width(),
4055 maxOuter.height() < QWIDGETSIZE_MAX ? maxOuter.height() : maxOuterHint.height()};
4108 mFillOrder(foColumnsFirst)
4131 if (column >= 0 && column <
mElements.first().size())
4136 qDebug() << Q_FUNC_INFO <<
"Requested cell is empty. Row:" << row <<
"Column:" << column;
4138 qDebug() << Q_FUNC_INFO <<
"Invalid column. Row:" << row <<
"Column:" << column;
4140 qDebug() << Q_FUNC_INFO <<
"Invalid row. Row:" << row <<
"Column:" << column;
4171 qDebug() << Q_FUNC_INFO <<
"There is already an element in the specified row/column:" << row << column;
4248 qDebug() << Q_FUNC_INFO <<
"Invalid stretch factor, must be positive:" << factor;
4250 qDebug() << Q_FUNC_INFO <<
"Invalid column:" << column;
4274 qDebug() << Q_FUNC_INFO <<
"Invalid stretch factor, must be positive:" <<
mColumnStretchFactors.at(i);
4279 qDebug() << Q_FUNC_INFO <<
"Column count not equal to passed stretch factor count:" << factors;
4301 qDebug() << Q_FUNC_INFO <<
"Invalid stretch factor, must be positive:" << factor;
4303 qDebug() << Q_FUNC_INFO <<
"Invalid row:" << row;
4327 qDebug() << Q_FUNC_INFO <<
"Invalid stretch factor, must be positive:" <<
mRowStretchFactors.at(i);
4332 qDebug() << Q_FUNC_INFO <<
"Row count not equal to passed stretch factor count:" << factors;
4374 mWrap = qMax(0, count);
4406 QVector<QCPLayoutElement*> tempElements;
4409 tempElements.reserve(elCount);
4410 for (
int i=0; i<elCount; ++i)
4413 tempElements.append(
takeAt(i));
4446 mElements.append(QList<QCPLayoutElement*>());
4450 int newColCount = qMax(
columnCount(), newColumnCount);
4453 while (
mElements.at(i).size() < newColCount)
4480 QList<QCPLayoutElement*> newRow;
4482 newRow.append(
nullptr);
4507 for (
int row=0; row<
rowCount(); ++row)
4508 mElements[row].insert(newIndex,
nullptr);
4536 qDebug() << Q_FUNC_INFO <<
"row index out of bounds:" << row;
4538 qDebug() << Q_FUNC_INFO <<
"column index out of bounds:" << column;
4563 if (nCols == 0 || nRows == 0)
4567 qDebug() << Q_FUNC_INFO <<
"index out of bounds:" << index;
4575 column = index / nRows;
4576 row = index % nRows;
4581 row = index / nCols;
4582 column = index % nCols;
4591 QVector<int> minColWidths, minRowHeights, maxColWidths, maxRowHeights;
4601 int yOffset =
mRect.top();
4602 for (
int row=0; row<
rowCount(); ++row)
4606 int xOffset =
mRect.left();
4612 mElements.at(row).at(col)->setOuterRect(QRect(xOffset, yOffset, colWidths.at(col), rowHeights.at(row)));
4655 qDebug() << Q_FUNC_INFO <<
"Attempt to take invalid index:" << index;
4673 qDebug() << Q_FUNC_INFO <<
"Element not in this layout, couldn't take";
4675 qDebug() << Q_FUNC_INFO <<
"Can't take nullptr element";
4682 QList<QCPLayoutElement*> result;
4684 #if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
4685 result.reserve(elCount);
4687 for (
int i=0; i<elCount; ++i)
4691 for (
int i=0; i<elCount; ++i)
4694 result << result.at(i)->elements(recursive);
4706 for (
int row=
rowCount()-1; row>=0; --row)
4708 bool hasElements =
false;
4729 bool hasElements =
false;
4730 for (
int row=0; row<
rowCount(); ++row)
4741 for (
int row=0; row<
rowCount(); ++row)
4750 QVector<int> minColWidths, minRowHeights;
4753 foreach (
int w, minColWidths)
4754 result.rwidth() += w;
4755 foreach (
int h, minRowHeights)
4756 result.rheight() += h;
4767 QVector<int> maxColWidths, maxRowHeights;
4771 foreach (
int w, maxColWidths)
4772 result.setWidth(qMin(result.width()+w, QWIDGETSIZE_MAX));
4773 foreach (
int h, maxRowHeights)
4774 result.setHeight(qMin(result.height()+h, QWIDGETSIZE_MAX));
4779 if (result.height() > QWIDGETSIZE_MAX)
4780 result.setHeight(QWIDGETSIZE_MAX);
4781 if (result.width() > QWIDGETSIZE_MAX)
4782 result.setWidth(QWIDGETSIZE_MAX);
4802 *minRowHeights = QVector<int>(
rowCount(), 0);
4803 for (
int row=0; row<
rowCount(); ++row)
4810 if (minColWidths->at(col) < minSize.width())
4811 (*minColWidths)[col] = minSize.width();
4812 if (minRowHeights->at(row) < minSize.height())
4813 (*minRowHeights)[row] = minSize.height();
4834 *maxColWidths = QVector<int>(
columnCount(), QWIDGETSIZE_MAX);
4835 *maxRowHeights = QVector<int>(
rowCount(), QWIDGETSIZE_MAX);
4836 for (
int row=0; row<
rowCount(); ++row)
4843 if (maxColWidths->at(col) > maxSize.width())
4844 (*maxColWidths)[col] = maxSize.width();
4845 if (maxRowHeights->at(row) > maxSize.height())
4846 (*maxRowHeights)[row] = maxSize.height();
4907 qDebug() << Q_FUNC_INFO <<
"Invalid element index:" << index;
4922 qDebug() << Q_FUNC_INFO <<
"Invalid element index:" << index;
4923 #if QT_VERSION < QT_VERSION_CHECK(5, 2, 0)
4941 qDebug() << Q_FUNC_INFO <<
"Invalid element index:" << index;
4956 qDebug() << Q_FUNC_INFO <<
"Invalid element index:" << index;
4972 qDebug() << Q_FUNC_INFO <<
"Invalid element index:" << index;
4991 qDebug() << Q_FUNC_INFO <<
"Invalid element index:" << index;
5009 if (
insetRect.size().width() < finalMinSize.width())
5010 insetRect.setWidth(finalMinSize.width());
5011 if (
insetRect.size().height() < finalMinSize.height())
5012 insetRect.setHeight(finalMinSize.height());
5013 if (
insetRect.size().width() > finalMaxSize.width())
5014 insetRect.setWidth(finalMaxSize.width());
5015 if (
insetRect.size().height() > finalMaxSize.height())
5016 insetRect.setHeight(finalMaxSize.height());
5021 if (al.testFlag(Qt::AlignLeft))
insetRect.moveLeft(
rect().x());
5022 else if (al.testFlag(Qt::AlignRight))
insetRect.moveRight(
rect().x()+
rect().width());
5023 else insetRect.moveLeft(
int(
rect().x()+
rect().width()*0.5-finalMinSize.width()*0.5 ));
5024 if (al.testFlag(Qt::AlignTop))
insetRect.moveTop(
rect().y());
5025 else if (al.testFlag(Qt::AlignBottom))
insetRect.moveBottom(
rect().y()+
rect().height());
5026 else insetRect.moveTop(
int(
rect().y()+
rect().height()*0.5-finalMinSize.height()*0.5 ));
5041 if (index >= 0 && index <
mElements.size())
5060 qDebug() << Q_FUNC_INFO <<
"Attempt to take invalid index:" << index;
5078 qDebug() << Q_FUNC_INFO <<
"Element not in this layout, couldn't take";
5080 qDebug() << Q_FUNC_INFO <<
"Can't take nullptr element";
5129 mInsetRect.append(QRectF(0.6, 0.6, 0.4, 0.4));
5132 qDebug() << Q_FUNC_INFO <<
"Can't add nullptr element";
5158 qDebug() << Q_FUNC_INFO <<
"Can't add nullptr element";
5339 QPen penBackup = painter->pen();
5340 QBrush brushBackup = painter->brush();
5341 QPen miterPen = penBackup;
5342 miterPen.setJoinStyle(Qt::MiterJoin);
5343 QBrush brush(painter->pen().color(), Qt::SolidPattern);
5349 QPointF points[3] = {pos.
toPointF(),
5350 (pos-lengthVec+widthVec).toPointF(),
5351 (pos-lengthVec-widthVec).toPointF()
5353 painter->
setPen(miterPen);
5354 painter->setBrush(brush);
5355 painter->drawConvexPolygon(points, 3);
5356 painter->setBrush(brushBackup);
5357 painter->
setPen(penBackup);
5362 QPointF points[4] = {pos.
toPointF(),
5363 (pos-lengthVec+widthVec).toPointF(),
5364 (pos-lengthVec*0.8).toPointF(),
5365 (pos-lengthVec-widthVec).toPointF()
5367 painter->
setPen(miterPen);
5368 painter->setBrush(brush);
5369 painter->drawConvexPolygon(points, 4);
5370 painter->setBrush(brushBackup);
5371 painter->
setPen(penBackup);
5376 QPointF points[3] = {(pos-lengthVec+widthVec).toPointF(),
5378 (pos-lengthVec-widthVec).toPointF()
5380 painter->
setPen(miterPen);
5381 painter->drawPolyline(points, 3);
5382 painter->
setPen(penBackup);
5387 painter->setBrush(brush);
5389 painter->setBrush(brushBackup);
5395 QPointF points[4] = {(pos-widthVecPerp+widthVec).toPointF(),
5396 (pos-widthVecPerp-widthVec).toPointF(),
5397 (pos+widthVecPerp-widthVec).toPointF(),
5398 (pos+widthVecPerp+widthVec).toPointF()
5400 painter->
setPen(miterPen);
5401 painter->setBrush(brush);
5402 painter->drawConvexPolygon(points, 4);
5403 painter->setBrush(brushBackup);
5404 painter->
setPen(penBackup);
5410 QPointF points[4] = {(pos-widthVecPerp).toPointF(),
5411 (pos-widthVec).toPointF(),
5412 (pos+widthVecPerp).toPointF(),
5413 (pos+widthVec).toPointF()
5415 painter->
setPen(miterPen);
5416 painter->setBrush(brush);
5417 painter->drawConvexPolygon(points, 4);
5418 painter->setBrush(brushBackup);
5419 painter->
setPen(penBackup);
5424 painter->
drawLine((pos+widthVec).toPointF(), (pos-widthVec).toPointF());
5436 shift = dir.
normalized()*qMax(qreal(1.0), painter->pen().widthF())*qreal(0.5);
5438 painter->
drawLine((pos+widthVec+lengthVec*0.2*(
mInverted?-1:1)+shift).toPointF(),
5439 (pos-widthVec-lengthVec*0.2*(
mInverted?-1:1)+shift).toPointF());
5485 mAnchorMode(amRectangular),
5486 mAnchorSide(asLeft),
5487 mAnchorReferenceType(artNormal),
5491 mSubstituteExponent(true),
5492 mMultiplicationSymbol(QChar(215)),
5493 mAbbreviateDecimalPowers(false),
5494 mParentPlot(parentPlot),
5586 if (realRotation > 90) realRotation -= 180;
5587 else if (realRotation < -90) realRotation += 180;
5655 result.append(QByteArray::number(
mRotation));
5659 result.append(
mColor.name().toLatin1()+QByteArray::number(
mColor.alpha(), 16));
5660 result.append(
mFont.toString().toLatin1());
5686 if (text.isEmpty())
return;
5699 bool labelClippedByBorder =
false;
5709 if (!labelClippedByBorder)
5711 painter->drawPixmap(pos+cachedLabel->
offset, cachedLabel->
pixmap);
5714 mLabelCache.insert(QString::fromUtf8(key), cachedLabel);
5719 bool labelClippedByBorder =
false;
5729 if (!labelClippedByBorder)
5769 return tickPos+(anchorNormal*
mPadding).toPointF();
5787 QTransform oldTransform = painter->transform();
5788 QFont oldFont = painter->font();
5789 QPen oldPen = painter->pen();
5792 painter->translate(pos);
5793 painter->setTransform(labelData.
transform,
true);
5796 painter->setFont(labelData.
baseFont);
5798 if (!labelData.
expPart.isEmpty())
5800 painter->drawText(0, 0, 0, 0, Qt::TextDontClip, labelData.
basePart);
5803 painter->setFont(labelData.
expFont);
5823 painter->setTransform(oldTransform);
5824 painter->setFont(oldFont);
5844 bool useBeautifulPowers =
false;
5849 ePos = text.indexOf(QLatin1Char(
'e'));
5850 if (ePos > 0 && text.at(ePos-1).isDigit())
5853 while (eLast+1 < text.size() && (text.at(eLast+1) == QLatin1Char(
'+') || text.at(eLast+1) == QLatin1Char(
'-') || text.at(eLast+1).isDigit()))
5856 useBeautifulPowers =
true;
5862 if (result.
baseFont.pointSizeF() > 0)
5865 QFontMetrics baseFontMetrics(result.
baseFont);
5866 if (useBeautifulPowers)
5873 result.
basePart = QLatin1String(
"10");
5876 result.
expPart = text.mid(ePos+1, eLast-ePos);
5878 while (result.
expPart.length() > 2 && result.
expPart.at(1) == QLatin1Char(
'0'))
5880 if (!result.
expPart.isEmpty() && result.
expPart.at(0) == QLatin1Char(
'+'))
5884 if (result.
expFont.pointSize() > 0)
5889 result.
baseBounds = baseFontMetrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip, result.
basePart);
5897 result.
totalBounds = baseFontMetrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip | Qt::AlignHCenter, result.
basePart);
5908 if (!qFuzzyIsNull(labelData.
rotation))
5964 #ifdef QCP_DEVICEPIXELRATIO_SUPPORTED
5965 # ifdef QCP_DEVICEPIXELRATIO_FLOAT
5973 result->
pixmap.fill(Qt::transparent);
5986 return text.toUtf8()+
5987 QByteArray::number(
color.red()+256*
color.green()+65536*
color.blue(), 36)+
5988 QByteArray::number(
color.alpha()+256*(
int)side, 36)+
5989 QByteArray::number((
int)(
rotation*100)%36000, 36);
5997 const double radius = anchorNormal.
length();
5998 const double sideHorz = sideExpandHorz*radius;
5999 const double sideVert = sideExpandVert*radius;
6000 if (anchorNormal.
x() > sideHorz)
6002 if (anchorNormal.
y() > sideVert)
return asTopLeft;
6005 }
else if (anchorNormal.
x() < -sideHorz)
6007 if (anchorNormal.
y() > sideVert)
return asTopRight;
6012 if (anchorNormal.
y() > 0)
return asTop;
6021 const bool rotateClockwise =
rotation > 0;
6024 if (!qFuzzyCompare(qAbs(
rotation), 90))
6049 const QFontMetrics fm(
mFont);
6120 mTickStepStrategy(tssReadability),
6153 qDebug() << Q_FUNC_INFO <<
"tick count must be greater than zero:" << count;
6182 void QCPAxisTicker::generate(
const QCPRange &range,
const QLocale &locale, QChar formatChar,
int precision, QVector<double> &ticks, QVector<double> *subTicks, QVector<QString> *tickLabels)
6192 if (!ticks.isEmpty())
6197 *subTicks = QVector<double>();
6235 double epsilon = 0.01;
6238 double fracPart = modf(
getMantissa(tickStep), &intPartf);
6239 intPart = int(intPartf);
6242 if (fracPart < epsilon || 1.0-fracPart < epsilon)
6244 if (1.0-fracPart < epsilon)
6248 case 1: result = 4;
break;
6249 case 2: result = 3;
break;
6250 case 3: result = 2;
break;
6251 case 4: result = 3;
break;
6252 case 5: result = 4;
break;
6253 case 6: result = 2;
break;
6254 case 7: result = 6;
break;
6255 case 8: result = 3;
break;
6256 case 9: result = 2;
break;
6261 if (qAbs(fracPart-0.5) < epsilon)
6265 case 1: result = 2;
break;
6266 case 2: result = 4;
break;
6267 case 3: result = 4;
break;
6268 case 4: result = 2;
break;
6269 case 5: result = 4;
break;
6270 case 6: result = 4;
break;
6271 case 7: result = 2;
break;
6272 case 8: result = 4;
break;
6273 case 9: result = 4;
break;
6295 return locale.toString(tick, formatChar.toLatin1(), precision);
6309 QVector<double> result;
6310 if (subTickCount <= 0 || ticks.size() < 2)
6313 result.reserve((ticks.size()-1)*subTickCount);
6314 for (
int i=1; i<ticks.size(); ++i)
6316 double subTickStep = (ticks.at(i)-ticks.at(i-1))/
double(subTickCount+1);
6317 for (
int k=1; k<=subTickCount; ++k)
6318 result.append(ticks.at(i-1) + k*subTickStep);
6340 QVector<double> result;
6344 int tickcount = int(lastStep-firstStep+1);
6345 if (tickcount < 0) tickcount = 0;
6346 result.resize(tickcount);
6347 for (
int i=0; i<tickcount; ++i)
6363 QVector<QString> result;
6364 result.reserve(ticks.size());
6365 foreach (
double tickCoord, ticks)
6366 result.append(
getTickLabel(tickCoord, locale, formatChar, precision));
6379 bool lowFound =
false;
6380 bool highFound =
false;
6384 for (
int i=0; i < ticks.size(); ++i)
6386 if (ticks.at(i) >= range.
lower)
6393 for (
int i=ticks.size()-1; i >= 0; --i)
6395 if (ticks.at(i) <= range.
upper)
6403 if (highFound && lowFound)
6405 int trimFront = qMax(0, lowIndex-(keepOneOutlier ? 1 : 0));
6406 int trimBack = qMax(0, ticks.size()-(keepOneOutlier ? 2 : 1)-highIndex);
6407 if (trimFront > 0 || trimBack > 0)
6408 ticks = ticks.mid(trimFront, ticks.size()-trimFront-trimBack);
6421 if (candidates.size() == 1)
6422 return candidates.first();
6423 QVector<double>::const_iterator it = std::lower_bound(candidates.constBegin(), candidates.constEnd(), target);
6424 if (it == candidates.constEnd())
6426 else if (it == candidates.constBegin())
6429 return target-*(it-1) < *it-target ? *(it-1) : *it;
6441 const double mag = qPow(10.0, qFloor(qLn(input)/qLn(10.0)));
6442 if (magnitude) *magnitude = mag;
6455 const double mantissa =
getMantissa(input, &magnitude);
6460 return pickClosest(mantissa, QVector<double>() << 1.0 << 2.0 << 2.5 << 5.0 << 10.0)*magnitude;
6465 if (mantissa <= 5.0)
6466 return int(mantissa*2)/2.0*magnitude;
6468 return int(mantissa/2.0)*2.0*magnitude;
6524 mDateTimeFormat(QLatin1String(
"hh:mm:ss\ndd.MM.yy")),
6525 mDateTimeSpec(Qt::LocalTime),
6526 mDateStrategy(dsNone)
6591 # if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
6652 }
else if (result < 86400*30.4375*12)
6655 << 1 << 2.5 << 5 << 10 << 15 << 30 << 60 << 2.5*60 << 5*60 << 10*60 << 15*60 << 30*60 << 60*60
6656 << 3600*2 << 3600*3 << 3600*6 << 3600*12 << 3600*24
6657 << 86400*2 << 86400*5 << 86400*7 << 86400*14 << 86400*30.4375 << 86400*30.4375*2 << 86400*30.4375*3 << 86400*30.4375*6 << 86400*30.4375*12);
6658 if (result > 86400*30.4375-1)
6660 else if (result > 3600*24-1)
6664 const double secondsPerYear = 86400*30.4375*12;
6665 result =
cleanMantissa(result/secondsPerYear)*secondsPerYear;
6681 switch (qRound(tickStep))
6683 case 5*60: result = 4;
break;
6684 case 10*60: result = 1;
break;
6685 case 15*60: result = 2;
break;
6686 case 30*60: result = 1;
break;
6687 case 60*60: result = 3;
break;
6688 case 3600*2: result = 3;
break;
6689 case 3600*3: result = 2;
break;
6690 case 3600*6: result = 1;
break;
6691 case 3600*12: result = 3;
break;
6692 case 3600*24: result = 3;
break;
6693 case 86400*2: result = 1;
break;
6694 case 86400*5: result = 4;
break;
6695 case 86400*7: result = 6;
break;
6696 case 86400*14: result = 1;
break;
6697 case int(86400*30.4375+0.5): result = 3;
break;
6698 case int(86400*30.4375*2+0.5): result = 1;
break;
6699 case int(86400*30.4375*3+0.5): result = 2;
break;
6700 case int(86400*30.4375*6+0.5): result = 5;
break;
6701 case int(86400*30.4375*12+0.5): result = 3;
break;
6717 Q_UNUSED(formatChar)
6718 # if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
6738 if (!result.isEmpty())
6743 QDateTime tickDateTime;
6744 for (
int i=0; i<result.size(); ++i)
6747 tickDateTime.setTime(uniformDateTime.time());
6753 QDateTime tickDateTime;
6754 for (
int i=0; i<result.size(); ++i)
6757 tickDateTime.setTime(uniformDateTime.time());
6758 int thisUniformDay = uniformDateTime.date().day() <= tickDateTime.date().daysInMonth() ? uniformDateTime.date().day() : tickDateTime.date().daysInMonth();
6759 if (thisUniformDay-tickDateTime.date().day() < -15)
6760 tickDateTime = tickDateTime.addMonths(1);
6761 else if (thisUniformDay-tickDateTime.date().day() > 15)
6762 tickDateTime = tickDateTime.addMonths(-1);
6763 tickDateTime.setDate(QDate(tickDateTime.date().year(), tickDateTime.date().month(), thisUniformDay));
6782 # if QT_VERSION < QT_VERSION_CHECK(4, 7, 0)
6783 return QDateTime::fromTime_t(key).addMSecs((key-(qint64)key)*1000);
6785 return QDateTime::fromMSecsSinceEpoch(qint64(key*1000.0));
6802 # if QT_VERSION < QT_VERSION_CHECK(4, 7, 0)
6803 return dateTime.toTime_t()+dateTime.time().msec()/1000.0;
6805 return dateTime.toMSecsSinceEpoch()/1000.0;
6822 # if QT_VERSION < QT_VERSION_CHECK(4, 7, 0)
6823 return QDateTime(date, QTime(0, 0), timeSpec).toTime_t();
6824 # elif QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
6825 return QDateTime(date, QTime(0, 0), timeSpec).toMSecsSinceEpoch()/1000.0;
6827 return date.startOfDay(timeSpec).toMSecsSinceEpoch()/1000.0;
6880 mTimeFormat(QLatin1String(
"%h:%m:%s")),
6881 mSmallestUnit(tuSeconds),
6882 mBiggestUnit(tuHours)
6924 bool hasSmallest =
false;
6971 }
else if (result < 3600*24)
6974 QVector<double> availableSteps;
6977 availableSteps << 1;
6979 availableSteps << 2.5;
6981 availableSteps << 2;
6983 availableSteps << 5 << 10 << 15 << 30;
6986 availableSteps << 1*60;
6988 availableSteps << 2.5*60;
6990 availableSteps << 2*60;
6992 availableSteps << 5*60 << 10*60 << 15*60 << 30*60;
6995 availableSteps << 1*3600 << 2*3600 << 3*3600 << 6*3600 << 12*3600 << 24*3600;
7000 const double secondsPerDay = 3600*24;
7015 switch (qRound(tickStep))
7017 case 5*60: result = 4;
break;
7018 case 10*60: result = 1;
break;
7019 case 15*60: result = 2;
break;
7020 case 30*60: result = 1;
break;
7021 case 60*60: result = 3;
break;
7022 case 3600*2: result = 3;
break;
7023 case 3600*3: result = 2;
break;
7024 case 3600*6: result = 1;
break;
7025 case 3600*12: result = 3;
break;
7026 case 3600*24: result = 3;
break;
7041 Q_UNUSED(formatChar)
7043 bool negative = tick < 0;
7044 if (negative) tick *= -1;
7046 double restValues[
tuDays+1];
7062 result.prepend(QLatin1Char(
'-'));
7073 QString valueStr = QString::number(value);
7075 valueStr.prepend(QLatin1Char(
'0'));
7114 mScaleStrategy(ssNone)
7132 qDebug() << Q_FUNC_INFO <<
"tick step must be greater than zero:" << step;
7271 qDebug() << Q_FUNC_INFO <<
"sub tick count can't be negative:" << subTicks;
7295 mTicks.insert(position, label);
7310 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
7330 if (positions.size() != labels.size())
7331 qDebug() << Q_FUNC_INFO <<
"passed unequal length vectors for positions and labels:" << positions.size() << labels.size();
7332 int n = qMin(positions.size(), labels.size());
7333 for (
int i=0; i<n; ++i)
7334 mTicks.insert(positions.at(i), labels.at(i));
7369 Q_UNUSED(formatChar)
7371 return mTicks.value(tick);
7384 QVector<double> result;
7388 QMap<double, QString>::const_iterator start =
mTicks.lowerBound(range.
lower);
7389 QMap<double, QString>::const_iterator end =
mTicks.upperBound(range.
upper);
7391 if (start !=
mTicks.constBegin()) --start;
7392 if (end !=
mTicks.constEnd()) ++end;
7393 for (QMap<double, QString>::const_iterator it = start; it != end; ++it)
7394 result.append(it.key());
7428 mPiSymbol(QLatin1String(
" ")+QChar(0x03C0)),
7431 mFractionStyle(fsUnicodeFractions),
7527 int denominator = 1000;
7528 int numerator = qRound(tickInPis*denominator);
7530 if (qAbs(numerator) == 1 && denominator == 1)
7531 return (numerator < 0 ? QLatin1String(
"-") : QLatin1String(
"")) +
mPiSymbol.trimmed();
7532 else if (numerator == 0)
7533 return QLatin1String(
"0");
7538 if (qFuzzyIsNull(tickInPis))
7539 return QLatin1String(
"0");
7540 else if (qFuzzyCompare(qAbs(tickInPis), 1.0))
7541 return (tickInPis < 0 ? QLatin1String(
"-") : QLatin1String(
"")) +
mPiSymbol.trimmed();
7555 if (numerator == 0 || denominator == 0)
7558 int num = numerator;
7559 int denom = denominator;
7562 int oldDenom = denom;
7563 denom = num % denom;
7582 if (denominator == 0)
7584 qDebug() << Q_FUNC_INFO <<
"called with zero denominator";
7589 qDebug() << Q_FUNC_INFO <<
"shouldn't be called with fraction style fsDecimal";
7590 return QString::number(numerator/
double(denominator));
7592 int sign = numerator*denominator < 0 ? -1 : 1;
7593 numerator = qAbs(numerator);
7594 denominator = qAbs(denominator);
7596 if (denominator == 1)
7598 return QString::number(sign*numerator);
7601 int integerPart = numerator/denominator;
7602 int remainder = numerator%denominator;
7605 return QString::number(sign*integerPart);
7610 return QString(QLatin1String(
"%1%2%3/%4"))
7611 .arg(sign == -1 ? QLatin1String(
"-") : QLatin1String(
""))
7612 .arg(integerPart > 0 ? QString::number(integerPart)+QLatin1String(
" ") : QString(QLatin1String(
"")))
7617 return QString(QLatin1String(
"%1%2%3"))
7618 .arg(sign == -1 ? QLatin1String(
"-") : QLatin1String(
""))
7619 .arg(integerPart > 0 ? QString::number(integerPart) : QLatin1String(
""))
7649 return QString(QChar(0x2070));
7654 const int digit = number%10;
7657 case 1: { result.prepend(QChar(0x00B9));
break; }
7658 case 2: { result.prepend(QChar(0x00B2));
break; }
7659 case 3: { result.prepend(QChar(0x00B3));
break; }
7660 default: { result.prepend(QChar(0x2070+digit));
break; }
7675 return QString(QChar(0x2080));
7680 result.prepend(QChar(0x2080+number%10));
7727 mLogBaseLnInv(1.0/qLn(mLogBase))
7742 qDebug() << Q_FUNC_INFO <<
"log base has to be greater than zero:" << base;
7760 qDebug() << Q_FUNC_INFO <<
"sub tick count can't be negative:" << subTicks;
7790 QVector<double> result;
7794 if (baseTickCount < 1.6)
7796 const double exactPowerStep = baseTickCount/double(
mTickCount+1e-10);
7798 double currentTick = qPow(newLogBase, qFloor(qLn(range.
lower)/qLn(newLogBase)));
7799 result.append(currentTick);
7800 while (currentTick < range.upper && currentTick > 0)
7802 currentTick *= newLogBase;
7803 result.append(currentTick);
7805 }
else if (range.
lower < 0 && range.
upper < 0)
7808 if (baseTickCount < 1.6)
7810 const double exactPowerStep = baseTickCount/double(
mTickCount+1e-10);
7812 double currentTick = -qPow(newLogBase, qCeil(qLn(-range.
lower)/qLn(newLogBase)));
7813 result.append(currentTick);
7814 while (currentTick < range.
upper && currentTick < 0)
7816 currentTick /= newLogBase;
7817 result.append(currentTick);
7821 qDebug() << Q_FUNC_INFO <<
"Invalid range for logarithmic plot: " << range.
lower <<
".." << range.
upper;
7856 QCPLayerable(parentAxis->parentPlot(), QString(), parentAxis),
7858 mAntialiasedSubGrid{},
7859 mAntialiasedZeroLine{},
7860 mParentAxis(parentAxis)
7863 setParent(parentAxis);
7864 setPen(QPen(QColor(200,200,200), 0, Qt::DotLine));
7865 setSubGridPen(QPen(QColor(220,220,220), 0, Qt::DotLine));
7866 setZeroLinePen(QPen(QColor(200,200,200), 0, Qt::SolidLine));
7867 setSubGridVisible(
false);
7868 setAntialiased(
false);
7869 setAntialiasedSubGrid(
false);
7870 setAntialiasedZeroLine(
false);
7951 if (!
mParentAxis) { qDebug() << Q_FUNC_INFO <<
"invalid parent axis";
return; }
7966 if (!
mParentAxis) { qDebug() << Q_FUNC_INFO <<
"invalid parent axis";
return; }
7973 int zeroLineIndex = -1;
7979 for (
int i=0; i<tickCount; ++i)
7993 for (
int i=0; i<tickCount; ++i)
7995 if (i == zeroLineIndex)
continue;
8002 int zeroLineIndex = -1;
8008 for (
int i=0; i<tickCount; ++i)
8022 for (
int i=0; i<tickCount; ++i)
8024 if (i == zeroLineIndex)
continue;
8039 if (!
mParentAxis) { qDebug() << Q_FUNC_INFO <<
"invalid parent axis";
return; }
8202 mOrientation(orientation(type)),
8203 mSelectableParts(spAxis | spTickLabels | spAxisLabel),
8204 mSelectedParts(spNone),
8205 mBasePen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
8206 mSelectedBasePen(QPen(Qt::blue, 2)),
8209 mLabelFont(mParentPlot->font()),
8210 mSelectedLabelFont(QFont(mLabelFont.family(), mLabelFont.pointSize(), QFont::Bold)),
8211 mLabelColor(Qt::black),
8212 mSelectedLabelColor(Qt::blue),
8215 mTickLabelFont(mParentPlot->font()),
8216 mSelectedTickLabelFont(QFont(mTickLabelFont.family(), mTickLabelFont.pointSize(), QFont::Bold)),
8217 mTickLabelColor(Qt::black),
8218 mSelectedTickLabelColor(Qt::blue),
8219 mNumberPrecision(6),
8220 mNumberFormatChar(
'g'),
8221 mNumberBeautifulPowers(true),
8225 mTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
8226 mSelectedTickPen(QPen(Qt::blue, 2)),
8227 mSubTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
8228 mSelectedSubTickPen(QPen(Qt::blue, 2)),
8231 mRangeReversed(false),
8232 mScaleType(stLinear),
8237 mCachedMarginValid(false),
8258 }
else if (type ==
atLeft)
8296 result.append(QLatin1Char(
'b'));
8298 result.append(QLatin1Char(
'c'));
8488 if (alignment == Qt::AlignLeft)
8490 else if (alignment == Qt::AlignRight)
8493 setRange(position-size/2.0, position+size/2.0);
8572 qDebug() << Q_FUNC_INFO <<
"can not set nullptr as axis ticker";
8712 if (formatCode.isEmpty())
8714 qDebug() << Q_FUNC_INFO <<
"Passed formatCode is empty";
8720 QString allowedFormatChars(QLatin1String(
"eEfgG"));
8721 if (allowedFormatChars.contains(formatCode.at(0)))
8726 qDebug() << Q_FUNC_INFO <<
"Invalid number format code (first char not in 'eEfgG'):" << formatCode;
8729 if (formatCode.length() < 2)
8742 qDebug() << Q_FUNC_INFO <<
"Invalid number format code (second char not 'b' or first char neither 'e' nor 'g'):" << formatCode;
8745 if (formatCode.length() < 3)
8752 if (formatCode.at(2) == QLatin1Char(
'c'))
8755 }
else if (formatCode.at(2) == QLatin1Char(
'd'))
8760 qDebug() << Q_FUNC_INFO <<
"Invalid number format code (third char neither 'c' nor 'd'):" << formatCode;
9170 qDebug() << Q_FUNC_INFO <<
"Center of scaling operation doesn't lie in same logarithmic sign domain as range:" << center;
9191 int otherPixelSize, ownPixelSize;
9203 double newRangeSize = ratio*otherAxis->
range().
size()*ownPixelSize/double(otherPixelSize);
9216 bool haveRange =
false;
9222 bool currentFoundRange;
9226 if (plottable->
keyAxis() ==
this)
9227 plottableRange = plottable->
getKeyRange(currentFoundRange, signDomain);
9229 plottableRange = plottable->
getValueRange(currentFoundRange, signDomain);
9230 if (currentFoundRange)
9233 newRange = plottableRange;
9235 newRange.
expand(plottableRange);
9243 double center = (newRange.
lower+newRange.
upper)*0.5;
9313 else if (value <= 0.0 && mRange.upper >= 0.0)
9335 else if (value <= 0.0 && mRange.upper >= 0.0)
9381 details->setValue(part);
9394 QList<QCPAbstractPlottable*> result;
9400 result.append(plottable);
9412 QList<QCPGraph*> result;
9418 result.append(graph);
9431 QList<QCPAbstractItem*> result;
9440 result.append(item);
9462 qDebug() << Q_FUNC_INFO <<
"Invalid margin side passed:" <<
static_cast<int>(side);
9478 qDebug() << Q_FUNC_INFO <<
"invalid axis type";
9491 if (selectionStateChanged)
9501 if (selectionStateChanged)
9531 if (event->buttons() & Qt::LeftButton)
9562 const double startPixel =
orientation() == Qt::Horizontal ? startPos.x() : startPos.y();
9563 const double currentPixel =
orientation() == Qt::Horizontal ?
event->pos().x() :
event->pos().y();
9630 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
9631 const double delta =
event->delta();
9633 const double delta =
event->angleDelta().y();
9636 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
9637 const QPointF pos =
event->pos();
9639 const QPointF pos =
event->position();
9642 const double wheelSteps = delta/120.0;
9676 QVector<double> subTickPositions;
9677 QVector<double> tickPositions;
9695 for (
int i=0; i<subTickCount; ++i)
9835 QVector<double> tickPositions;
9896 basePen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
9900 tickLabelPadding(0),
9901 tickLabelRotation(0),
9902 tickLabelSide(
QCPAxis::lsOutside),
9903 substituteExponent(true),
9904 numberMultiplyCross(false),
9908 subTickLengthOut(0),
9909 tickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
9910 subTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
9912 abbreviateDecimalPowers(false),
9913 reversedEndings(false),
9914 mParentPlot(parentPlot),
9948 double xCor = 0, yCor = 0;
9960 baseLine.setPoints(origin+QPointF(xCor, yCor), origin+QPointF(
axisRect.width()+xCor, yCor));
9962 baseLine.setPoints(origin+QPointF(xCor, yCor), origin+QPointF(xCor, -
axisRect.height()+yCor));
9964 baseLine = QLineF(baseLine.p2(), baseLine.p1());
10004 painter->setBrush(QBrush(
basePen.color()));
10005 QCPVector2D baseLineVector(baseLine.dx(), baseLine.dy());
10016 oldClipRect = painter->clipRegion().boundingRect();
10019 QSize tickLabelsSize(0, 0);
10027 int distanceToAxis = margin;
10030 for (
int i=0; i<maxLabelIndex; ++i)
10036 painter->setClipRect(oldClipRect);
10040 if (!
label.isEmpty())
10045 labelBounds = painter->fontMetrics().boundingRect(0, 0, 0, 0, Qt::TextDontClip,
label);
10048 QTransform oldTransform = painter->transform();
10049 painter->translate((origin.x()-margin-labelBounds.height()), origin.y());
10050 painter->rotate(-90);
10051 painter->drawText(0, 0,
axisRect.height(), labelBounds.height(), Qt::TextDontClip | Qt::AlignCenter,
label);
10052 painter->setTransform(oldTransform);
10056 QTransform oldTransform = painter->transform();
10057 painter->translate((origin.x()+margin+labelBounds.height()), origin.y()-
axisRect.height());
10058 painter->rotate(90);
10059 painter->drawText(0, 0,
axisRect.height(), labelBounds.height(), Qt::TextDontClip | Qt::AlignCenter,
label);
10060 painter->setTransform(oldTransform);
10063 painter->drawText(origin.x(), origin.y()-margin-labelBounds.height(),
axisRect.width(), labelBounds.height(), Qt::TextDontClip | Qt::AlignCenter,
label);
10065 painter->drawText(origin.x(), origin.y()+margin,
axisRect.width(), labelBounds.height(), Qt::TextDontClip | Qt::AlignCenter,
label);
10069 int selectionTolerance = 0;
10073 qDebug() << Q_FUNC_INFO <<
"mParentPlot is null";
10075 int selAxisInSize = selectionTolerance;
10076 int selTickLabelSize;
10077 int selTickLabelOffset;
10080 selTickLabelSize = (
QCPAxis::orientation(
type) == Qt::Horizontal ? tickLabelsSize.height() : tickLabelsSize.width());
10084 selTickLabelSize = -(
QCPAxis::orientation(
type) == Qt::Horizontal ? tickLabelsSize.height() : tickLabelsSize.width());
10087 int selLabelSize = labelBounds.height();
10141 QSize tickLabelsSize(0, 0);
10144 foreach (
const QString &tickLabel,
tickLabels)
10152 if (!
label.isEmpty())
10156 bounds = fontMetrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip | Qt::AlignHCenter | Qt::AlignVCenter,
label);
10216 if (text.isEmpty())
return;
10218 QPointF labelAnchor;
10237 #ifdef QCP_DEVICEPIXELRATIO_SUPPORTED
10238 # ifdef QCP_DEVICEPIXELRATIO_FLOAT
10246 cachedLabel->
pixmap.fill(Qt::transparent);
10248 cachePainter.
setPen(painter->pen());
10252 bool labelClippedByBorder =
false;
10260 if (!labelClippedByBorder)
10262 painter->drawPixmap(labelAnchor+cachedLabel->
offset, cachedLabel->
pixmap);
10271 bool labelClippedByBorder =
false;
10279 if (!labelClippedByBorder)
10281 drawTickLabel(painter, finalPosition.x(), finalPosition.y(), labelData);
10287 if (finalSize.width() > tickLabelsSize->width())
10288 tickLabelsSize->setWidth(finalSize.width());
10289 if (finalSize.height() > tickLabelsSize->height())
10290 tickLabelsSize->setHeight(finalSize.height());
10305 QTransform oldTransform = painter->transform();
10306 QFont oldFont = painter->font();
10309 painter->translate(x, y);
10314 if (!labelData.
expPart.isEmpty())
10316 painter->setFont(labelData.
baseFont);
10317 painter->drawText(0, 0, 0, 0, Qt::TextDontClip, labelData.
basePart);
10320 painter->setFont(labelData.
expFont);
10324 painter->setFont(labelData.
baseFont);
10325 painter->drawText(0, 0, labelData.
totalBounds.width(), labelData.
totalBounds.height(), Qt::TextDontClip | Qt::AlignHCenter, labelData.
basePart);
10329 painter->setTransform(oldTransform);
10330 painter->setFont(oldFont);
10346 bool useBeautifulPowers =
false;
10351 ePos = text.indexOf(QLatin1Char(
'e'));
10352 if (ePos > 0 && text.at(ePos-1).isDigit())
10355 while (eLast+1 < text.size() && (text.at(eLast+1) == QLatin1Char(
'+') || text.at(eLast+1) == QLatin1Char(
'-') || text.at(eLast+1).isDigit()))
10358 useBeautifulPowers =
true;
10364 if (result.
baseFont.pointSizeF() > 0)
10366 if (useBeautifulPowers)
10369 result.
basePart = text.left(ePos);
10373 result.
basePart = QLatin1String(
"10");
10376 result.
expPart = text.mid(ePos+1, eLast-ePos);
10378 while (result.
expPart.length() > 2 && result.
expPart.at(1) == QLatin1Char(
'0'))
10380 if (!result.
expPart.isEmpty() && result.
expPart.at(0) == QLatin1Char(
'+'))
10384 if (result.
expFont.pointSize() > 0)
10385 result.
expFont.setPointSize(
int(result.
expFont.pointSize()*0.75));
10387 result.
expFont.setPixelSize(
int(result.
expFont.pixelSize()*0.75));
10397 result.
totalBounds = QFontMetrics(result.
baseFont).boundingRect(0, 0, 0, 0, Qt::TextDontClip | Qt::AlignHCenter, result.
basePart);
10405 QTransform transform;
10446 x = -qCos(radians)*labelData.
totalBounds.width();
10464 x = +qSin(radians)*labelData.
totalBounds.height();
10486 x = -qSin(-radians)*labelData.
totalBounds.height()/2.0;
10487 y = -qCos(-radians)*labelData.
totalBounds.height();
10500 x = +qSin(radians)*labelData.
totalBounds.height()/2.0;
10505 y = +qSin(-radians)*labelData.
totalBounds.width();
10539 if (finalSize.width() > tickLabelsSize->width())
10540 tickLabelsSize->setWidth(finalSize.width());
10541 if (finalSize.height() > tickLabelsSize->height())
10542 tickLabelsSize->setHeight(finalSize.height());
10639 mBrush(Qt::NoBrush),
10655 mBrush(Qt::NoBrush),
10668 mBrush(Qt::NoBrush),
10681 mBrush(QBrush(fill)),
10706 mPenDefined(pen.style() != Qt::NoPen)
10718 mBrush(Qt::NoBrush),
10738 mCustomPath(customPath),
10739 mPenDefined(pen.style() != Qt::NoPen)
10748 if (properties.testFlag(
spPen))
10754 if (properties.testFlag(
spBrush))
10756 if (properties.testFlag(
spSize))
10758 if (properties.testFlag(
spShape))
10864 painter->setBrush(
mBrush);
10885 double w =
mSize/2.0;
10891 painter->
drawLine(QPointF(x, y), QPointF(x+0.0001, y));
10896 painter->
drawLine(QLineF(x-w, y-w, x+w, y+w));
10897 painter->
drawLine(QLineF(x-w, y+w, x+w, y-w));
10902 painter->
drawLine(QLineF(x-w, y, x+w, y));
10903 painter->
drawLine(QLineF( x, y+w, x, y-w));
10908 painter->drawEllipse(QPointF(x , y), w, w);
10913 QBrush b = painter->brush();
10914 painter->setBrush(painter->pen().color());
10915 painter->drawEllipse(QPointF(x , y), w, w);
10916 painter->setBrush(b);
10921 painter->drawRect(QRectF(x-w, y-w,
mSize,
mSize));
10926 QPointF lineArray[4] = {QPointF(x-w, y),
10930 painter->drawPolygon(lineArray, 4);
10935 painter->
drawLine(QLineF(x-w, y, x+w, y));
10936 painter->
drawLine(QLineF( x, y+w, x, y-w));
10937 painter->
drawLine(QLineF(x-w*0.707, y-w*0.707, x+w*0.707, y+w*0.707));
10938 painter->
drawLine(QLineF(x-w*0.707, y+w*0.707, x+w*0.707, y-w*0.707));
10943 QPointF lineArray[3] = {QPointF(x-w, y+0.755*w),
10944 QPointF(x+w, y+0.755*w),
10945 QPointF( x, y-0.977*w)};
10946 painter->drawPolygon(lineArray, 3);
10951 QPointF lineArray[3] = {QPointF(x-w, y-0.755*w),
10952 QPointF(x+w, y-0.755*w),
10953 QPointF( x, y+0.977*w)};
10954 painter->drawPolygon(lineArray, 3);
10959 painter->drawRect(QRectF(x-w, y-w,
mSize,
mSize));
10960 painter->
drawLine(QLineF(x-w, y-w, x+w*0.95, y+w*0.95));
10961 painter->
drawLine(QLineF(x-w, y+w*0.95, x+w*0.95, y-w));
10966 painter->drawRect(QRectF(x-w, y-w,
mSize,
mSize));
10967 painter->
drawLine(QLineF(x-w, y, x+w*0.95, y));
10968 painter->
drawLine(QLineF( x, y+w, x, y-w));
10973 painter->drawEllipse(QPointF(x, y), w, w);
10974 painter->
drawLine(QLineF(x-w*0.707, y-w*0.707, x+w*0.670, y+w*0.670));
10975 painter->
drawLine(QLineF(x-w*0.707, y+w*0.670, x+w*0.670, y-w*0.707));
10980 painter->drawEllipse(QPointF(x, y), w, w);
10981 painter->
drawLine(QLineF(x-w, y, x+w, y));
10982 painter->
drawLine(QLineF( x, y+w, x, y-w));
10987 painter->drawEllipse(QPointF(x, y), w, w);
10988 painter->
drawLine(QLineF(x, y-w, x, y+w));
10989 painter->
drawLine(QLineF(x, y, x-w*0.707, y+w*0.707));
10990 painter->
drawLine(QLineF(x, y, x+w*0.707, y+w*0.707));
10995 const double widthHalf =
mPixmap.width()*0.5;
10996 const double heightHalf =
mPixmap.height()*0.5;
10997 #if QT_VERSION < QT_VERSION_CHECK(4, 8, 0)
10998 const QRectF clipRect = painter->clipRegion().boundingRect().adjusted(-widthHalf, -heightHalf, widthHalf, heightHalf);
11000 const QRectF clipRect = painter->clipBoundingRect().adjusted(-widthHalf, -heightHalf, widthHalf, heightHalf);
11002 if (clipRect.contains(x, y))
11003 painter->drawPixmap(qRound(x-widthHalf), qRound(y-heightHalf),
mPixmap);
11008 QTransform oldTransform = painter->transform();
11009 painter->translate(x, y);
11012 painter->setTransform(oldTransform);
11057 mPen(QColor(80, 80, 255), 2.5),
11058 mBrush(Qt::NoBrush),
11060 mPlottable(nullptr)
11126 painter->setBrush(
mBrush);
11173 Q_UNUSED(selection)
11193 qDebug() << Q_FUNC_INFO <<
"This selection decorator is already registered with plottable:" <<
reinterpret_cast<quintptr
>(
mPlottable);
11415 QCPLayerable(keyAxis->parentPlot(), QString(), keyAxis->axisRect()),
11417 mAntialiasedFill(true),
11418 mAntialiasedScatters(true),
11420 mBrush(Qt::NoBrush),
11422 mValueAxis(valueAxis),
11424 mSelectionDecorator(nullptr)
11427 qDebug() << Q_FUNC_INFO <<
"Parent plot of keyAxis is not the same as that of valueAxis.";
11429 qDebug() << Q_FUNC_INFO <<
"keyAxis and valueAxis must be orthogonal to each other.";
11629 if (!
keyAxis || !
valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return; }
11650 if (!
keyAxis || !
valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return QPointF(); }
11671 if (!
keyAxis || !
valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return; }
11720 if (!
keyAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key axis";
return; }
11734 double center = (newRange.
lower+newRange.
upper)*0.5;
11763 if (!
keyAxis || !
valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return; }
11777 double center = (newRange.
lower+newRange.
upper)*0.5;
11810 qDebug() << Q_FUNC_INFO <<
"passed legend is null";
11815 qDebug() << Q_FUNC_INFO <<
"passed legend isn't in the same QCustomPlot as this plottable";
11855 qDebug() << Q_FUNC_INFO <<
"passed legend is null";
11972 if (selectionStateChanged)
11973 *selectionStateChanged =
mSelection != selectionBefore;
11984 if (selectionStateChanged)
11985 *selectionStateChanged =
mSelection != selectionBefore;
12040 mParentPlot(parentPlot),
12041 mParentItem(parentItem),
12042 mAnchorId(anchorId)
12076 qDebug() << Q_FUNC_INFO <<
"no valid anchor id set:" <<
mAnchorId;
12081 qDebug() << Q_FUNC_INFO <<
"no parent item set";
12099 qDebug() << Q_FUNC_INFO <<
"provided pos is child already" <<
reinterpret_cast<quintptr
>(pos);
12111 qDebug() << Q_FUNC_INFO <<
"provided pos isn't child" <<
reinterpret_cast<quintptr
>(pos);
12127 qDebug() << Q_FUNC_INFO <<
"provided pos is child already" <<
reinterpret_cast<quintptr
>(pos);
12139 qDebug() << Q_FUNC_INFO <<
"provided pos isn't child" <<
reinterpret_cast<quintptr
>(pos);
12214 mPositionTypeX(ptAbsolute),
12215 mPositionTypeY(ptAbsolute),
12218 mParentAnchorX(nullptr),
12219 mParentAnchorY(nullptr)
12295 bool retainPixelPosition =
true;
12297 retainPixelPosition =
false;
12299 retainPixelPosition =
false;
12302 if (retainPixelPosition)
12307 if (retainPixelPosition)
12325 bool retainPixelPosition =
true;
12327 retainPixelPosition =
false;
12329 retainPixelPosition =
false;
12332 if (retainPixelPosition)
12337 if (retainPixelPosition)
12364 return successX && successY;
12379 qDebug() << Q_FUNC_INFO <<
"can't set self as parent anchor" <<
reinterpret_cast<quintptr
>(
parentAnchor);
12384 while (currentParent)
12389 if (currentParentPos ==
this)
12391 qDebug() << Q_FUNC_INFO <<
"can't create recursive parent-child-relationship" <<
reinterpret_cast<quintptr
>(
parentAnchor);
12394 currentParent = currentParentPos->parentAnchorX();
12402 qDebug() << Q_FUNC_INFO <<
"can't set parent to be an anchor which itself depends on this position" <<
reinterpret_cast<quintptr
>(
parentAnchor);
12415 if (keepPixelPosition)
12425 if (keepPixelPosition)
12444 qDebug() << Q_FUNC_INFO <<
"can't set self as parent anchor" <<
reinterpret_cast<quintptr
>(
parentAnchor);
12449 while (currentParent)
12454 if (currentParentPos ==
this)
12456 qDebug() << Q_FUNC_INFO <<
"can't create recursive parent-child-relationship" <<
reinterpret_cast<quintptr
>(
parentAnchor);
12459 currentParent = currentParentPos->parentAnchorY();
12467 qDebug() << Q_FUNC_INFO <<
"can't set parent to be an anchor which itself depends on this position" <<
reinterpret_cast<quintptr
>(
parentAnchor);
12480 if (keepPixelPosition)
12490 if (keepPixelPosition)
12545 result.rx() =
mKey;
12567 result.rx() +=
mAxisRect.data()->left();
12569 qDebug() << Q_FUNC_INFO <<
"Item position type x is ptAxisRectRatio, but no axis rect was defined";
12579 qDebug() << Q_FUNC_INFO <<
"Item position type x is ptPlotCoords, but no axes were defined";
12611 result.ry() +=
mAxisRect.data()->top();
12613 qDebug() << Q_FUNC_INFO <<
"Item position type y is ptAxisRectRatio, but no axis rect was defined";
12623 qDebug() << Q_FUNC_INFO <<
"Item position type y is ptPlotCoords, but no axes were defined";
12692 x /= double(
mAxisRect.data()->width());
12694 qDebug() << Q_FUNC_INFO <<
"Item position type x is ptAxisRectRatio, but no axis rect was defined";
12700 x =
mKeyAxis.data()->pixelToCoord(x);
12704 qDebug() << Q_FUNC_INFO <<
"Item position type x is ptPlotCoords, but no axes were defined";
12734 y /= double(
mAxisRect.data()->height());
12736 qDebug() << Q_FUNC_INFO <<
"Item position type y is ptAxisRectRatio, but no axis rect was defined";
12742 x =
mKeyAxis.data()->pixelToCoord(y);
12746 qDebug() << Q_FUNC_INFO <<
"Item position type y is ptPlotCoords, but no axes were defined";
12929 mClipToAxisRect(false),
12936 if (!rects.isEmpty())
13039 qDebug() << Q_FUNC_INFO <<
"position with name not found:" << name;
13060 qDebug() << Q_FUNC_INFO <<
"anchor with name not found:" << name;
13132 double result = -1;
13135 const QList<QLineF> lines = QList<QLineF>() << QLineF(rect.topLeft(), rect.topRight()) << QLineF(rect.bottomLeft(), rect.bottomRight())
13136 << QLineF(rect.topLeft(), rect.bottomLeft()) << QLineF(rect.topRight(), rect.bottomRight());
13138 double minDistSqr = (std::numeric_limits<double>::max)();
13139 foreach (
const QLineF &line, lines)
13142 if (distSqr < minDistSqr)
13143 minDistSqr = distSqr;
13145 result = qSqrt(minDistSqr);
13150 if (rect.contains(pos))
13168 qDebug() << Q_FUNC_INFO <<
"called on item which shouldn't have any anchors (this method not reimplemented). anchorId" << anchorId;
13189 qDebug() << Q_FUNC_INFO <<
"anchor/position with name exists already:" << name;
13198 return newPosition;
13223 qDebug() << Q_FUNC_INFO <<
"anchor/position with name exists already:" << name;
13238 if (selectionStateChanged)
13239 *selectionStateChanged =
mSelected != selBefore;
13250 if (selectionStateChanged)
13251 *selectionStateChanged =
mSelected != selBefore;
13600 mBufferDevicePixelRatio(1.0),
13601 mPlotLayout(nullptr),
13602 mAutoAddPlottableToLegend(true),
13606 mSelectionTolerance(8),
13607 mNoAntialiasingOnDrag(false),
13608 mBackgroundBrush(Qt::white, Qt::SolidPattern),
13609 mBackgroundScaled(true),
13610 mBackgroundScaledMode(Qt::KeepAspectRatioByExpanding),
13611 mCurrentLayer(nullptr),
13613 mMultiSelectModifier(Qt::ControlModifier),
13615 mSelectionRect(nullptr),
13617 mMouseHasMoved(false),
13618 mMouseEventLayerable(nullptr),
13619 mMouseSignalLayerable(nullptr),
13620 mReplotting(false),
13621 mReplotQueued(false),
13623 mReplotTimeAverage(0),
13624 mOpenGlMultisamples(16),
13625 mOpenGlAntialiasedElementsBackup(
QCP::
aeNone),
13626 mOpenGlCacheLabelsBackup(true)
13628 setAttribute(Qt::WA_NoMousePropagation);
13629 setAttribute(Qt::WA_OpaquePaintEvent);
13630 setFocusPolicy(Qt::ClickFocus);
13631 setMouseTracking(
true);
13632 QLocale currentLocale = locale();
13633 currentLocale.setNumberOptions(QLocale::OmitGroupSeparator);
13634 setLocale(currentLocale);
13635 #ifdef QCP_DEVICEPIXELRATIO_SUPPORTED
13636 # ifdef QCP_DEVICEPIXELRATIO_FLOAT
13672 defaultAxisRect->
setLayer(QLatin1String(
"background"));
14066 #ifdef QCUSTOMPLOT_USE_OPENGL
14080 qDebug() << Q_FUNC_INFO <<
"Failed to enable OpenGL, continuing plotting without hardware acceleration.";
14097 qDebug() << Q_FUNC_INFO <<
"QCustomPlot can't use OpenGL because QCUSTOMPLOT_USE_OPENGL was not defined during compilation (add 'DEFINES += QCUSTOMPLOT_USE_OPENGL' to your qmake .pro file)";
14139 #ifdef QCP_DEVICEPIXELRATIO_SUPPORTED
14141 foreach (QSharedPointer<QCPAbstractPaintBuffer> buffer,
mPaintBuffers)
14145 qDebug() << Q_FUNC_INFO <<
"Device pixel ratios not supported for Qt versions before 5.4";
14246 qDebug() << Q_FUNC_INFO <<
"index out of bounds:" << index;
14279 qDebug() << Q_FUNC_INFO <<
"plottable not in list:" <<
reinterpret_cast<quintptr
>(
plottable);
14304 qDebug() << Q_FUNC_INFO <<
"index out of bounds:" << index;
14320 for (
int i=c-1; i >= 0; --i)
14344 QList<QCPAbstractPlottable*> result;
14364 return plottableAt<QCPAbstractPlottable>(pos, onlySelectable, dataIndex);
14385 if (index >= 0 && index <
mGraphs.size())
14390 qDebug() << Q_FUNC_INFO <<
"index out of bounds:" << index;
14425 if (!keyAxis) keyAxis =
xAxis;
14426 if (!valueAxis) valueAxis =
yAxis;
14427 if (!keyAxis || !valueAxis)
14429 qDebug() << Q_FUNC_INFO <<
"can't use default QCustomPlot xAxis or yAxis, because at least one is invalid (has been deleted)";
14434 qDebug() << Q_FUNC_INFO <<
"passed keyAxis or valueAxis doesn't have this QCustomPlot as parent";
14439 newGraph->
setName(QLatin1String(
"Graph ")+QString::number(
mGraphs.size()));
14464 if (index >= 0 && index <
mGraphs.size())
14481 for (
int i=c-1; i >= 0; --i)
14506 QList<QCPGraph*> result;
14510 result.append(
graph);
14525 if (index >= 0 && index <
mItems.size())
14527 return mItems.at(index);
14530 qDebug() << Q_FUNC_INFO <<
"index out of bounds:" << index;
14567 qDebug() << Q_FUNC_INFO <<
"item not in list:" <<
reinterpret_cast<quintptr
>(
item);
14578 if (index >= 0 && index <
mItems.size())
14582 qDebug() << Q_FUNC_INFO <<
"index out of bounds:" << index;
14597 for (
int i=c-1; i >= 0; --i)
14619 QList<QCPAbstractItem*> result;
14623 result.append(
item);
14639 return itemAt<QCPAbstractItem>(pos, onlySelectable);
14678 if (index >= 0 && index <
mLayers.size())
14683 qDebug() << Q_FUNC_INFO <<
"index out of bounds:" << index;
14713 qDebug() << Q_FUNC_INFO <<
"layer with name doesn't exist:" << name;
14730 qDebug() << Q_FUNC_INFO <<
"layer not a layer of this QCustomPlot:" <<
reinterpret_cast<quintptr
>(
layer);
14765 if (!
mLayers.contains(otherLayer))
14767 qDebug() << Q_FUNC_INFO <<
"otherLayer not a layer of this QCustomPlot:" <<
reinterpret_cast<quintptr
>(otherLayer);
14772 qDebug() << Q_FUNC_INFO <<
"A layer exists already with the name" << name;
14801 qDebug() << Q_FUNC_INFO <<
"layer not a layer of this QCustomPlot:" <<
reinterpret_cast<quintptr
>(
layer);
14806 qDebug() << Q_FUNC_INFO <<
"can't remove last layer";
14812 bool isFirstLayer = removedIndex==0;
14816 std::reverse(children.begin(), children.end());
14825 if (QSharedPointer<QCPAbstractPaintBuffer> pb =
layer->
mPaintBuffer.toStrongRef())
14826 pb->setInvalidated();
14848 qDebug() << Q_FUNC_INFO <<
"layer not a layer of this QCustomPlot:" <<
reinterpret_cast<quintptr
>(
layer);
14851 if (!
mLayers.contains(otherLayer))
14853 qDebug() << Q_FUNC_INFO <<
"otherLayer not a layer of this QCustomPlot:" <<
reinterpret_cast<quintptr
>(otherLayer);
14863 if (QSharedPointer<QCPAbstractPaintBuffer> pb =
layer->
mPaintBuffer.toStrongRef())
14864 pb->setInvalidated();
14865 if (QSharedPointer<QCPAbstractPaintBuffer> pb = otherLayer->
mPaintBuffer.toStrongRef())
14866 pb->setInvalidated();
14907 const QList<QCPAxisRect*> rectList =
axisRects();
14908 if (index >= 0 && index < rectList.size())
14910 return rectList.at(index);
14913 qDebug() << Q_FUNC_INFO <<
"invalid axis rect index" << index;
14931 QList<QCPAxisRect*> result;
14932 QStack<QCPLayoutElement*> elementStack;
14936 while (!elementStack.isEmpty())
14942 elementStack.push(element);
14943 if (
QCPAxisRect *ar = qobject_cast<QCPAxisRect*>(element))
14964 bool searchSubElements =
true;
14965 while (searchSubElements && currentElement)
14967 searchSubElements =
false;
14972 currentElement = subElement;
14973 searchSubElements =
true;
14978 return currentElement;
14995 bool searchSubElements =
true;
14996 while (searchSubElements && currentElement)
14998 searchSubElements =
false;
15003 currentElement = subElement;
15004 searchSubElements =
true;
15005 if (
QCPAxisRect *ar = qobject_cast<QCPAxisRect*>(currentElement))
15023 QList<QCPAxis*> result, allAxes;
15025 allAxes << rect->
axes();
15027 foreach (
QCPAxis *axis, allAxes)
15030 result.append(axis);
15045 QList<QCPLegend*> result;
15047 QStack<QCPLayoutElement*> elementStack;
15051 while (!elementStack.isEmpty())
15057 elementStack.push(subElement);
15058 if (
QCPLegend *leg = qobject_cast<QCPLegend*>(subElement))
15061 result.append(leg);
15122 QTimer::singleShot(0,
this, SLOT(
replot()));
15133 # if QT_VERSION < QT_VERSION_CHECK(4, 8, 0)
15135 replotTimer.start();
15137 QElapsedTimer replotTimer;
15138 replotTimer.start();
15146 foreach (QSharedPointer<QCPAbstractPaintBuffer> buffer,
mPaintBuffers)
15147 buffer->setInvalidated(
false);
15154 # if QT_VERSION < QT_VERSION_CHECK(4, 8, 0)
15189 QList<QCPAxis*> allAxes;
15191 allAxes << rect->
axes();
15193 foreach (
QCPAxis *axis, allAxes)
15194 axis->
rescale(onlyVisiblePlottables);
15236 bool success =
false;
15237 #ifdef QT_NO_PRINTER
15239 Q_UNUSED(exportPen)
15242 Q_UNUSED(pdfCreator)
15244 qDebug() << Q_FUNC_INFO <<
"Qt was built without printer support (QT_NO_PRINTER). PDF not created.";
15246 int newWidth, newHeight;
15247 if (width == 0 || height == 0)
15249 newWidth = this->width();
15250 newHeight = this->height();
15254 newHeight = height;
15257 QPrinter printer(QPrinter::ScreenResolution);
15258 printer.setOutputFileName(fileName);
15259 printer.setOutputFormat(QPrinter::PdfFormat);
15260 printer.setColorMode(QPrinter::Color);
15261 printer.printEngine()->setProperty(QPrintEngine::PPK_Creator, pdfCreator);
15262 printer.printEngine()->setProperty(QPrintEngine::PPK_DocumentName, pdfTitle);
15265 #if QT_VERSION < QT_VERSION_CHECK(5, 3, 0)
15266 printer.setFullPage(
true);
15267 printer.setPaperSize(
viewport().size(), QPrinter::DevicePixel);
15269 QPageLayout pageLayout;
15270 pageLayout.setMode(QPageLayout::FullPageMode);
15271 pageLayout.setOrientation(QPageLayout::Portrait);
15272 pageLayout.setMargins(QMarginsF(0, 0, 0, 0));
15273 pageLayout.setPageSize(QPageSize(
viewport().size(), QPageSize::Point, QString(), QPageSize::ExactMatch));
15274 printer.setPageLayout(pageLayout);
15277 if (printpainter.
begin(&printer))
15288 draw(&printpainter);
15289 printpainter.end();
15293 #endif // QT_NO_PRINTER
15344 return saveRastered(fileName, width, height, scale,
"PNG", quality, resolution, resolutionUnit);
15391 return saveRastered(fileName, width, height, scale,
"JPG", quality, resolution, resolutionUnit);
15435 return saveRastered(fileName, width, height, scale,
"BMP", -1, resolution, resolutionUnit);
15470 if (painter.isActive())
15472 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
15473 painter.setRenderHint(QPainter::HighQualityAntialiasing);
15478 foreach (QSharedPointer<QCPAbstractPaintBuffer> buffer,
mPaintBuffers)
15479 buffer->draw(&painter);
15512 QList<QVariant> details;
15514 for (
int i=0; i<candidates.size(); ++i)
15517 candidates.at(i)->mouseDoubleClickEvent(event, details.at(i));
15518 if (event->isAccepted())
15527 if (!candidates.isEmpty())
15533 dataIndex = details.first().value<
QCPDataSelection>().dataRange().begin();
15535 }
else if (
QCPAxis *ax = qobject_cast<QCPAxis*>(candidates.first()))
15537 else if (
QCPAbstractItem *ai = qobject_cast<QCPAbstractItem*>(candidates.first()))
15539 else if (
QCPLegend *lg = qobject_cast<QCPLegend*>(candidates.first()))
15571 QList<QVariant> details;
15573 if (!candidates.isEmpty())
15579 for (
int i=0; i<candidates.size(); ++i)
15582 candidates.at(i)->mousePressEvent(event, details.at(i));
15583 if (event->isAccepted())
15644 if (event->button() == Qt::LeftButton)
15694 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
15695 const QPointF pos =
event->pos();
15697 const QPointF pos =
event->position();
15705 if (event->isAccepted())
15822 int bufferIndex = 0;
15826 for (
int layerIndex = 0; layerIndex <
mLayers.size(); ++layerIndex)
15850 foreach (QSharedPointer<QCPAbstractPaintBuffer> buffer,
mPaintBuffers)
15852 buffer->setSize(
viewport().size());
15853 buffer->clear(Qt::transparent);
15854 buffer->setInvalidated();
15870 #if defined(QCP_OPENGL_FBO)
15872 #elif defined(QCP_OPENGL_PBUFFER)
15875 qDebug() << Q_FUNC_INFO <<
"OpenGL enabled even though no support for it compiled in, this shouldn't have happened. Falling back to pixmap paint buffer.";
15895 foreach (QSharedPointer<QCPAbstractPaintBuffer> buffer,
mPaintBuffers)
15897 if (buffer->invalidated())
15918 #ifdef QCP_OPENGL_FBO
15920 QSurfaceFormat proposedSurfaceFormat;
15922 #ifdef QCP_OPENGL_OFFSCREENSURFACE
15923 QOffscreenSurface *surface =
new QOffscreenSurface;
15925 QWindow *surface =
new QWindow;
15926 surface->setSurfaceType(QSurface::OpenGLSurface);
15928 surface->setFormat(proposedSurfaceFormat);
15930 mGlSurface = QSharedPointer<QSurface>(surface);
15931 mGlContext = QSharedPointer<QOpenGLContext>(
new QOpenGLContext);
15932 mGlContext->setFormat(mGlSurface->format());
15933 if (!mGlContext->create())
15935 qDebug() << Q_FUNC_INFO <<
"Failed to create OpenGL context";
15936 mGlContext.clear();
15937 mGlSurface.clear();
15940 if (!mGlContext->makeCurrent(mGlSurface.data()))
15942 qDebug() << Q_FUNC_INFO <<
"Failed to make opengl context current";
15943 mGlContext.clear();
15944 mGlSurface.clear();
15947 if (!QOpenGLFramebufferObject::hasOpenGLFramebufferObjects())
15949 qDebug() << Q_FUNC_INFO <<
"OpenGL of this system doesn't support frame buffer objects";
15950 mGlContext.clear();
15951 mGlSurface.clear();
15954 mGlPaintDevice = QSharedPointer<QOpenGLPaintDevice>(
new QOpenGLPaintDevice);
15956 #elif defined(QCP_OPENGL_PBUFFER)
15957 return QGLFormat::hasOpenGL();
15976 #ifdef QCP_OPENGL_FBO
15977 mGlPaintDevice.clear();
15978 mGlContext.clear();
15979 mGlSurface.clear();
16009 if (this->legend ==
legend)
16010 this->legend =
nullptr;
16032 typedef QPair<QCPAbstractPlottable*, QCPDataSelection> SelectionCandidate;
16033 typedef QMultiMap<int, SelectionCandidate> SelectionCandidates;
16035 bool selectionStateChanged =
false;
16039 SelectionCandidates potentialSelections;
16040 QRectF rectF(rect.normalized());
16048 QCPDataSelection dataSel = plottableInterface->selectTestRect(rectF,
true);
16057 if (!potentialSelections.isEmpty())
16059 SelectionCandidates::iterator it = potentialSelections.begin();
16060 while (it != std::prev(potentialSelections.end()))
16061 it = potentialSelections.erase(it);
16074 if ((potentialSelections.isEmpty() || potentialSelections.constBegin()->first != layerable) &&
mInteractions.testFlag(layerable->
selectionCategory()))
16076 bool selChanged =
false;
16078 selectionStateChanged |= selChanged;
16085 SelectionCandidates::const_iterator it = potentialSelections.constEnd();
16086 while (it != potentialSelections.constBegin())
16089 if (
mInteractions.testFlag(it.value().first->selectionCategory()))
16091 bool selChanged =
false;
16092 it.value().first->selectEvent(event, additive, QVariant::fromValue(it.value().second), &selChanged);
16093 selectionStateChanged |= selChanged;
16099 if (selectionStateChanged)
16124 affectedAxes.removeAll(
static_cast<QCPAxis*
>(
nullptr));
16151 bool selectionStateChanged =
false;
16162 bool selChanged =
false;
16164 selectionStateChanged |= selChanged;
16172 bool selChanged =
false;
16173 clickedLayerable->
selectEvent(event, additive, details, &selChanged);
16174 selectionStateChanged |= selChanged;
16176 if (selectionStateChanged)
16198 qDebug() << Q_FUNC_INFO <<
"plottable already added to this QCustomPlot:" <<
reinterpret_cast<quintptr
>(
plottable);
16203 qDebug() << Q_FUNC_INFO <<
"plottable not created with this QCustomPlot as parent:" <<
reinterpret_cast<quintptr
>(
plottable);
16229 qDebug() << Q_FUNC_INFO <<
"passed graph is zero";
16234 qDebug() << Q_FUNC_INFO <<
"graph already registered with this QCustomPlot";
16256 qDebug() << Q_FUNC_INFO <<
"item already added to this QCustomPlot:" <<
reinterpret_cast<quintptr
>(
item);
16261 qDebug() << Q_FUNC_INFO <<
"item not created with this QCustomPlot as parent:" <<
reinterpret_cast<quintptr
>(
item);
16279 for (
int i=0; i<
mLayers.size(); ++i)
16300 QList<QVariant> details;
16301 QList<QCPLayerable*> candidates =
layerableListAt(pos, onlySelectable, selectionDetails ? &details :
nullptr);
16302 if (selectionDetails && !details.isEmpty())
16303 *selectionDetails = details.first();
16304 if (!candidates.isEmpty())
16305 return candidates.first();
16331 QList<QCPLayerable*> result;
16332 for (
int layerIndex=
mLayers.size()-1; layerIndex>=0; --layerIndex)
16334 const QList<QCPLayerable*> layerables =
mLayers.at(layerIndex)->children();
16335 for (
int i=layerables.size()-1; i>=0; --i)
16337 if (!layerables.at(i)->realVisibility())
16340 double dist = layerables.at(i)->selectTest(pos, onlySelectable, selectionDetails ? &details :
nullptr);
16343 result.append(layerables.at(i));
16344 if (selectionDetails)
16345 selectionDetails->append(details);
16372 QImage buffer =
toPixmap(width, height, scale).toImage();
16374 int dotsPerMeter = 0;
16375 switch (resolutionUnit)
16381 buffer.setDotsPerMeterX(dotsPerMeter);
16382 buffer.setDotsPerMeterY(dotsPerMeter);
16383 if (!buffer.isNull())
16384 return buffer.save(fileName, format, quality);
16400 int newWidth, newHeight;
16401 if (width == 0 || height == 0)
16403 newWidth = this->width();
16404 newHeight = this->height();
16408 newHeight = height;
16410 int scaledWidth = qRound(scale*newWidth);
16411 int scaledHeight = qRound(scale*newHeight);
16413 QPixmap result(scaledWidth, scaledHeight);
16416 painter.
begin(&result);
16417 if (painter.isActive())
16422 if (!qFuzzyCompare(scale, 1.0))
16426 painter.scale(scale, scale);
16435 qDebug() << Q_FUNC_INFO <<
"Couldn't activate painter on pixmap";
16456 int newWidth, newHeight;
16457 if (width == 0 || height == 0)
16459 newWidth = this->width();
16460 newHeight = this->height();
16464 newHeight = height;
16467 if (painter->isActive())
16477 qDebug() << Q_FUNC_INFO <<
"Passed painter is not active";
16528 mColorInterpolation(ciRGB),
16529 mNanHandling(nhNone),
16530 mNanColor(Qt::black),
16532 mColorBufferInvalidated(true)
16545 mColorInterpolation(ciRGB),
16546 mNanHandling(nhNone),
16547 mNanColor(Qt::black),
16549 mColorBufferInvalidated(true)
16558 return ((other.
mLevelCount == this->mLevelCount) &&
16561 (other.
mNanColor == this->mNanColor) &&
16562 (other.
mPeriodic == this->mPeriodic) &&
16576 qDebug() << Q_FUNC_INFO <<
"n must be greater or equal 2 but was" << n;
16695 qDebug() << Q_FUNC_INFO <<
"null pointer given as data";
16700 qDebug() << Q_FUNC_INFO <<
"null pointer given as scanLine";
16708 for (
int i=0; i<n; ++i)
16710 const double value = data[dataIndexFactor*i];
16711 if (skipNanCheck || !std::isnan(value))
16713 int index = int((!logarithmic ? value-range.
lower : qLn(value/range.
lower)) * posToIndexFactor);
16730 case nhTransparent: scanLine[i] = qRgba(0, 0, 0, 0);
break;
16751 qDebug() << Q_FUNC_INFO <<
"null pointer given as data";
16756 qDebug() << Q_FUNC_INFO <<
"null pointer given as alpha";
16761 qDebug() << Q_FUNC_INFO <<
"null pointer given as scanLine";
16769 for (
int i=0; i<n; ++i)
16771 const double value = data[dataIndexFactor*i];
16772 if (skipNanCheck || !std::isnan(value))
16774 int index = int((!logarithmic ? value-range.
lower : qLn(value/range.
lower)) * posToIndexFactor);
16784 if (alpha[dataIndexFactor*i] == 255)
16790 const float alphaF = alpha[dataIndexFactor*i]/255.0f;
16791 scanLine[i] = qRgba(
int(qRed(rgb)*alphaF),
int(qGreen(rgb)*alphaF),
int(qBlue(rgb)*alphaF),
int(qAlpha(rgb)*alphaF));
16799 case nhTransparent: scanLine[i] = qRgba(0, 0, 0, 0);
break;
16826 if (!skipNanCheck && std::isnan(position))
16834 case nhNone:
return qRgba(0, 0, 0, 0);
16839 int index = int((!logarithmic ? position-range.
lower : qLn(position/range.
lower)) * posToIndexFactor);
16984 for (QMap<double, QColor>::const_iterator it=
mColorStops.constBegin(); it!=
mColorStops.constEnd(); ++it)
16996 for (QMap<double, QColor>::const_iterator it=
mColorStops.constBegin(); it!=
mColorStops.constEnd(); ++it)
16998 if (it.value().alpha() < 255)
17015 double indexToPosFactor = 1.0/double(
mLevelCount-1);
17019 double position = i*indexToPosFactor;
17020 QMap<double, QColor>::const_iterator it =
mColorStops.lowerBound(position);
17025 const QColor col = std::prev(it).value();
17026 const double alphaPremultiplier = col.alpha()/255.0;
17027 mColorBuffer[i] = qRgba(
int(col.red()*alphaPremultiplier),
17028 int(col.green()*alphaPremultiplier),
17029 int(col.blue()*alphaPremultiplier),
17037 const QColor &col = it.value();
17038 const double alphaPremultiplier = col.alpha()/255.0;
17039 mColorBuffer[i] = qRgba(
int(col.red()*alphaPremultiplier),
17040 int(col.green()*alphaPremultiplier),
17041 int(col.blue()*alphaPremultiplier),
17047 QMap<double, QColor>::const_iterator high = it;
17048 QMap<double, QColor>::const_iterator low = std::prev(it);
17049 double t = (position-low.key())/(high.key()-low.key());
17056 const int alpha = int((1-t)*low.value().alpha() + t*high.value().alpha());
17057 const double alphaPremultiplier = alpha/255.0;
17058 mColorBuffer[i] = qRgba(
int( ((1-t)*low.value().red() + t*high.value().red())*alphaPremultiplier ),
17059 int( ((1-t)*low.value().green() + t*high.value().green())*alphaPremultiplier ),
17060 int( ((1-t)*low.value().blue() + t*high.value().blue())*alphaPremultiplier ),
17064 mColorBuffer[i] = qRgb(
int( ((1-t)*low.value().red() + t*high.value().red()) ),
17065 int( ((1-t)*low.value().green() + t*high.value().green()) ),
17066 int( ((1-t)*low.value().blue() + t*high.value().blue())) );
17072 QColor lowHsv = low.value().toHsv();
17073 QColor highHsv = high.value().toHsv();
17075 double hueDiff = highHsv.hueF()-lowHsv.hueF();
17077 hue = lowHsv.hueF() - t*(1.0-hueDiff);
17078 else if (hueDiff < -0.5)
17079 hue = lowHsv.hueF() + t*(1.0+hueDiff);
17081 hue = lowHsv.hueF() + t*hueDiff;
17082 if (hue < 0) hue += 1.0;
17083 else if (hue >= 1.0) hue -= 1.0;
17086 const QRgb rgb = QColor::fromHsvF(hue,
17087 (1-t)*lowHsv.saturationF() + t*highHsv.saturationF(),
17088 (1-t)*lowHsv.valueF() + t*highHsv.valueF()).rgb();
17089 const double alpha = (1-t)*lowHsv.alphaF() + t*highHsv.alphaF();
17090 mColorBuffer[i] = qRgba(
int(qRed(rgb)*alpha),
int(qGreen(rgb)*alpha),
int(qBlue(rgb)*alpha),
int(255*alpha));
17095 (1-t)*lowHsv.saturationF() + t*highHsv.saturationF(),
17096 (1-t)*lowHsv.valueF() + t*highHsv.valueF()).rgb();
17105 const QRgb rgb =
mColorStops.constBegin().value().rgb();
17106 const double alpha =
mColorStops.constBegin().value().alphaF();
17107 mColorBuffer.fill(qRgba(
int(qRed(rgb)*alpha),
int(qGreen(rgb)*alpha),
int(qBlue(rgb)*alpha),
int(255*alpha)));
17144 mBracketPen(QPen(Qt::black)),
17145 mBracketBrush(Qt::NoBrush),
17147 mBracketHeight(50),
17148 mBracketStyle(bsSquareBracket),
17149 mTangentToData(false),
17276 qDebug() << Q_FUNC_INFO <<
"unknown/custom bracket style can't be handeld by default implementation:" <<
static_cast<int>(
mBracketStyle);
17300 int closeBracketDir = -openBracketDir;
17303 double openBracketAngle = 0;
17304 double closeBracketAngle = 0;
17308 closeBracketAngle =
getTangentAngle(interface1d, dataRange.
end()-1, closeBracketDir);
17311 QTransform oldTransform = painter->transform();
17314 painter->translate(openBracketPos);
17315 painter->rotate(openBracketAngle/M_PI*180.0);
17317 painter->setTransform(oldTransform);
17321 painter->translate(closeBracketPos);
17322 painter->rotate(closeBracketAngle/M_PI*180.0);
17324 painter->setTransform(oldTransform);
17344 if (!interface1d || dataIndex < 0 || dataIndex >= interface1d->
dataCount())
17346 direction = direction < 0 ? -1 : 1;
17354 qDebug() << averageCount;
17356 QVector<QPointF> points(averageCount);
17357 QPointF pointsAverage;
17358 int currentIndex = dataIndex;
17359 for (
int i=0; i<averageCount; ++i)
17362 pointsAverage += points[i];
17363 currentIndex += direction;
17365 pointsAverage /= double(averageCount);
17369 double denomSum = 0;
17370 for (
int i=0; i<averageCount; ++i)
17372 const double dx = points.at(i).x()-pointsAverage.x();
17373 const double dy = points.at(i).y()-pointsAverage.y();
17377 if (!qFuzzyIsNull(denomSum) && !qFuzzyIsNull(numSum))
17379 return qAtan2(numSum, denomSum);
17393 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return {0, 0}; }
17538 mBackgroundBrush(Qt::NoBrush),
17539 mBackgroundScaled(true),
17540 mBackgroundScaledMode(Qt::KeepAspectRatioByExpanding),
17542 mRangeDrag(Qt::Horizontal|Qt::Vertical),
17543 mRangeZoom(Qt::Horizontal|Qt::Vertical),
17544 mRangeZoomFactorHorz(0.85),
17545 mRangeZoomFactorVert(0.85),
17559 if (setupDefaultAxes)
17596 return mAxes.value(type).size();
17606 QList<QCPAxis*> ax(
mAxes.value(type));
17607 if (index >= 0 && index < ax.size())
17609 return ax.at(index);
17612 qDebug() << Q_FUNC_INFO <<
"Axis index out of bounds:" << index;
17627 QList<QCPAxis*> result;
17645 QList<QCPAxis*> result;
17646 QHashIterator<QCPAxis::AxisType, QList<QCPAxis*> > it(
mAxes);
17647 while (it.hasNext())
17650 result << it.value();
17680 newAxis =
new QCPAxis(
this, type);
17685 qDebug() << Q_FUNC_INFO <<
"passed axis has different axis type than specified in type parameter";
17690 qDebug() << Q_FUNC_INFO <<
"passed axis doesn't have this axis rect as parent axis rect";
17693 if (
axes().contains(newAxis))
17695 qDebug() << Q_FUNC_INFO <<
"passed axis is already owned by this axis rect";
17699 if (!
mAxes[type].isEmpty())
17705 mAxes[type].append(newAxis);
17732 QList<QCPAxis*> result;
17754 QHashIterator<QCPAxis::AxisType, QList<QCPAxis*> > it(
mAxes);
17755 while (it.hasNext())
17758 if (it.value().contains(
axis))
17760 if (it.value().first() ==
axis && it.value().size() > 1)
17763 if (qobject_cast<QCustomPlot*>(
parentPlot()))
17769 qDebug() << Q_FUNC_INFO <<
"Axis isn't in axis rect:" <<
reinterpret_cast<quintptr
>(
axis);
17800 qDebug() << Q_FUNC_INFO <<
"a passed axis was zero";
17805 pixelRange =
QCPRange(pixelRect.left(), pixelRect.right());
17807 pixelRange =
QCPRange(pixelRect.top(), pixelRect.bottom());
17833 QCPAxis *xAxis, *yAxis, *xAxis2, *yAxis2;
17867 xAxis2->
ticker()->setTickCount(xAxis->
ticker()->tickCount());
17868 xAxis2->
ticker()->setTickOrigin(xAxis->
ticker()->tickOrigin());
17876 yAxis2->
ticker()->setTickCount(yAxis->
ticker()->tickCount());
17877 yAxis2->
ticker()->setTickOrigin(yAxis->
ticker()->tickOrigin());
17881 connect(xAxis, SIGNAL(rangeChanged(
QCPRange)), xAxis2, SLOT(setRange(
QCPRange)));
17882 connect(yAxis, SIGNAL(rangeChanged(
QCPRange)), yAxis2, SLOT(setRange(
QCPRange)));
17897 QList<QCPAbstractPlottable*> result;
17901 result.append(plottable);
17917 QList<QCPGraph*> result;
17921 result.append(graph);
17940 QList<QCPAbstractItem*> result;
17945 result.append(item);
17950 if (position->
axisRect() ==
this ||
17954 result.append(item);
17999 QList<QCPLayoutElement*> result;
18108 if (orientation == Qt::Horizontal)
18122 if (orientation == Qt::Horizontal)
18135 QList<QCPAxis*> result;
18136 if (orientation == Qt::Horizontal)
18140 if (!
axis.isNull())
18141 result.append(
axis.data());
18147 if (!
axis.isNull())
18148 result.append(
axis.data());
18161 QList<QCPAxis*> result;
18162 if (orientation == Qt::Horizontal)
18166 if (!
axis.isNull())
18167 result.append(
axis.data());
18173 if (!
axis.isNull())
18174 result.append(
axis.data());
18244 QList<QCPAxis*> horz, vert;
18246 horz.append(horizontal);
18248 vert.append(vertical);
18263 QList<QCPAxis*> horz, vert;
18283 foreach (
QCPAxis *ax, horizontal)
18285 QPointer<QCPAxis> axPointer(ax);
18286 if (!axPointer.isNull())
18289 qDebug() << Q_FUNC_INFO <<
"invalid axis passed in horizontal list:" <<
reinterpret_cast<quintptr
>(ax);
18292 foreach (
QCPAxis *ax, vertical)
18294 QPointer<QCPAxis> axPointer(ax);
18295 if (!axPointer.isNull())
18298 qDebug() << Q_FUNC_INFO <<
"invalid axis passed in vertical list:" <<
reinterpret_cast<quintptr
>(ax);
18316 QList<QCPAxis*> horz, vert;
18318 horz.append(horizontal);
18320 vert.append(vertical);
18335 QList<QCPAxis*> horz, vert;
18355 foreach (
QCPAxis *ax, horizontal)
18357 QPointer<QCPAxis> axPointer(ax);
18358 if (!axPointer.isNull())
18361 qDebug() << Q_FUNC_INFO <<
"invalid axis passed in horizontal list:" <<
reinterpret_cast<quintptr
>(ax);
18364 foreach (
QCPAxis *ax, vertical)
18366 QPointer<QCPAxis> axPointer(ax);
18367 if (!axPointer.isNull())
18370 qDebug() << Q_FUNC_INFO <<
"invalid axis passed in vertical list:" <<
reinterpret_cast<quintptr
>(ax);
18454 const QList<QCPAxis*> axesList =
mAxes.value(type);
18455 if (axesList.isEmpty())
18458 bool isFirstVisible = !axesList.first()->visible();
18459 for (
int i=1; i<axesList.size(); ++i)
18461 int offset = axesList.at(i-1)->offset() + axesList.at(i-1)->calculateMargin();
18462 if (axesList.at(i)->visible())
18464 if (!isFirstVisible)
18465 offset += axesList.at(i)->tickLengthIn();
18466 isFirstVisible =
false;
18468 axesList.at(i)->setOffset(offset);
18476 qDebug() << Q_FUNC_INFO <<
"Called with side that isn't specified as auto margin";
18482 if (!axesList.isEmpty())
18483 return axesList.last()->offset() + axesList.last()->calculateMargin();
18527 if (event->buttons() & Qt::LeftButton)
18644 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
18645 const double delta =
event->delta();
18647 const double delta =
event->angleDelta().y();
18650 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
18651 const QPointF pos =
event->pos();
18653 const QPointF pos =
event->position();
18662 double wheelSteps = delta/120.0;
18668 if (!
axis.isNull())
18677 if (!
axis.isNull())
18735 mParentLegend(parent),
18736 mFont(parent->font()),
18737 mTextColor(parent->textColor()),
18738 mSelectedFont(parent->selectedFont()),
18739 mSelectedTextColor(parent->selectedTextColor()),
18743 setLayer(QLatin1String(
"legend"));
18828 if (
mRect.contains(pos.toPoint()))
18855 if (selectionStateChanged)
18856 *selectionStateChanged =
mSelected != selBefore;
18867 if (selectionStateChanged)
18868 *selectionStateChanged =
mSelected != selBefore;
18909 mPlottable(plottable)
18956 QRect textRect = painter->fontMetrics().boundingRect(0, 0, 0, iconSize.height(), Qt::TextDontClip,
mPlottable->
name());
18957 QRect iconRect(
mRect.topLeft(), iconSize);
18958 int textHeight = qMax(textRect.height(), iconSize.height());
18962 painter->setClipRect(iconRect, Qt::IntersectClip);
18969 painter->setBrush(Qt::NoBrush);
18970 int halfPen = qCeil(painter->pen().widthF()*0.5)+1;
18971 painter->setClipRect(
mOuterRect.adjusted(-halfPen, -halfPen, halfPen, halfPen));
18972 painter->drawRect(iconRect);
18986 QSize result(0, 0);
18988 QFontMetrics fontMetrics(
getFont());
18990 textRect = fontMetrics.boundingRect(0, 0, 0, iconSize.height(), Qt::TextDontClip,
mPlottable->
name());
18992 result.setHeight(qMax(textRect.height(), iconSize.height()));
19061 setColumnSpacing(8);
19062 setMargins(QMargins(7, 5, 7, 4));
19063 setAntialiased(
false);
19064 setIconSize(32, 18);
19066 setIconTextPadding(7);
19068 setSelectableParts(spLegendBox | spItems);
19069 setSelectedParts(spNone);
19071 setBorderPen(QPen(Qt::black, 0));
19072 setSelectedBorderPen(QPen(Qt::blue, 2));
19073 setIconBorderPen(Qt::NoPen);
19074 setSelectedIconBorderPen(QPen(Qt::blue, 2));
19075 setBrush(Qt::white);
19076 setSelectedBrush(Qt::white);
19077 setTextColor(Qt::black);
19078 setSelectedTextColor(Qt::blue);
19092 bool hasSelectedItems =
false;
19097 hasSelectedItems =
true;
19101 if (hasSelectedItems)
19241 SelectableParts newSelected = selected;
19248 qDebug() << Q_FUNC_INFO <<
"spItems flag can not be set, it can only be unset with this function";
19340 return qobject_cast<QCPAbstractLegendItem*>(
elementAt(index));
19355 if (pli->plottable() == plottable)
19435 bool success =
remove(ali);
19484 QList<QCPAbstractLegendItem*> result;
19489 if (ali->selected())
19490 result.append(ali);
19573 if (selectionStateChanged)
19586 if (selectionStateChanged)
19663 mTextFlags(Qt::AlignCenter),
19664 mFont(QFont(QLatin1String(
"sans serif"), 12)),
19665 mTextColor(Qt::black),
19666 mSelectedFont(QFont(QLatin1String(
"sans serif"), 12)),
19667 mSelectedTextColor(Qt::blue),
19668 mSelectable(false),
19688 mTextFlags(Qt::AlignCenter),
19689 mFont(QFont(QLatin1String(
"sans serif"), 12)),
19690 mTextColor(Qt::black),
19691 mSelectedFont(QFont(QLatin1String(
"sans serif"), 12)),
19692 mSelectedTextColor(Qt::blue),
19693 mSelectable(false),
19713 mTextFlags(Qt::AlignCenter),
19714 mFont(QFont(QLatin1String(
"sans serif"), int(pointSize))),
19715 mTextColor(Qt::black),
19716 mSelectedFont(QFont(QLatin1String(
"sans serif"), int(pointSize))),
19717 mSelectedTextColor(Qt::blue),
19718 mSelectable(false),
19721 mFont.setPointSizeF(pointSize);
19725 mFont.setPointSizeF(pointSize);
19741 mTextFlags(Qt::AlignCenter),
19742 mFont(QFont(fontFamily, int(pointSize))),
19743 mTextColor(Qt::black),
19744 mSelectedFont(QFont(fontFamily, int(pointSize))),
19745 mSelectedTextColor(Qt::blue),
19746 mSelectable(false),
19749 mFont.setPointSizeF(pointSize);
19762 mTextFlags(Qt::AlignCenter),
19764 mTextColor(Qt::black),
19765 mSelectedFont(font),
19766 mSelectedTextColor(Qt::blue),
19767 mSelectable(false),
19896 QFontMetrics metrics(
mFont);
19897 QSize result(metrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip,
mText).size());
19906 QFontMetrics metrics(
mFont);
19907 QSize result(metrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip,
mText).size());
19908 result.setWidth(QWIDGETSIZE_MAX);
19922 if (selectionStateChanged)
19923 *selectionStateChanged =
mSelected != selBefore;
19934 if (selectionStateChanged)
19935 *selectionStateChanged =
mSelected != selBefore;
19981 if ((QPointF(event->pos())-startPos).manhattanLength() <= 3)
20111 mDataScaleType(
QCPAxis::stLinear),
20131 qDebug() << Q_FUNC_INFO <<
"internal color axis undefined";
20143 qDebug() << Q_FUNC_INFO <<
"internal axis rect was deleted";
20157 qDebug() << Q_FUNC_INFO <<
"internal axis rect was deleted";
20177 qDebug() << Q_FUNC_INFO <<
"internal axis rect was deleted";
20184 QString labelTransfer;
20185 QSharedPointer<QCPAxisTicker> tickerTransfer;
20192 tickerTransfer =
mColorAxis.data()->ticker();
20210 mColorAxis.data()->setTicker(tickerTransfer);
20283 mAxisRect.data()->mGradientImageInvalidated =
true;
20296 qDebug() << Q_FUNC_INFO <<
"internal color axis undefined";
20322 qDebug() << Q_FUNC_INFO <<
"internal axis rect was deleted";
20331 #if QT_VERSION < QT_VERSION_CHECK(5, 2, 0)
20332 mAxisRect.data()->setRangeDrag(
nullptr);
20349 qDebug() << Q_FUNC_INFO <<
"internal axis rect was deleted";
20358 #if QT_VERSION < QT_VERSION_CHECK(5, 2, 0)
20359 mAxisRect.data()->setRangeDrag(
nullptr);
20371 QList<QCPColorMap*> result;
20375 if (cm->colorScale() ==
this)
20389 QList<QCPColorMap*> maps =
colorMaps();
20391 bool haveRange =
false;
20402 bool currentFoundRange =
true;
20406 if (mapRange.
lower <= 0 && mapRange.
upper > 0)
20408 else if (mapRange.
lower <= 0 && mapRange.
upper <= 0)
20409 currentFoundRange =
false;
20412 if (mapRange.
upper >= 0 && mapRange.
lower < 0)
20414 else if (mapRange.
upper >= 0 && mapRange.
lower >= 0)
20415 currentFoundRange =
false;
20417 if (currentFoundRange)
20420 newRange = mapRange;
20422 newRange.
expand(mapRange);
20431 double center = (newRange.
lower+newRange.
upper)*0.5;
20452 qDebug() << Q_FUNC_INFO <<
"internal axis rect was deleted";
20493 qDebug() << Q_FUNC_INFO <<
"internal axis rect was deleted";
20496 mAxisRect.data()->mousePressEvent(event, details);
20504 qDebug() << Q_FUNC_INFO <<
"internal axis rect was deleted";
20507 mAxisRect.data()->mouseMoveEvent(event, startPos);
20515 qDebug() << Q_FUNC_INFO <<
"internal axis rect was deleted";
20518 mAxisRect.data()->mouseReleaseEvent(event, startPos);
20526 qDebug() << Q_FUNC_INFO <<
"internal axis rect was deleted";
20551 QCPAxisRect(parentColorScale->parentPlot(), true),
20552 mParentColorScale(parentColorScale),
20553 mGradientImageInvalidated(true)
20563 connect(
axis(type), SIGNAL(selectionChanged(QCPAxis::SelectableParts)),
this, SLOT(
axisSelectionChanged(QCPAxis::SelectableParts)));
20564 connect(
axis(type), SIGNAL(selectableChanged(QCPAxis::SelectableParts)),
this, SLOT(
axisSelectableChanged(QCPAxis::SelectableParts)));
20595 bool mirrorHorz =
false;
20596 bool mirrorVert =
false;
20603 painter->drawImage(
rect().adjusted(0, -1, 0, -1),
mGradientImage.mirrored(mirrorHorz, mirrorVert));
20614 if (
rect().isEmpty())
20617 const QImage::Format format = QImage::Format_ARGB32_Premultiplied;
20620 QVector<double> data(n);
20621 for (
int i=0; i<n; ++i)
20626 h =
rect().height();
20628 QVector<QRgb*> pixels;
20629 for (
int y=0; y<h; ++y)
20630 pixels.append(
reinterpret_cast<QRgb*
>(
mGradientImage.scanLine(y)));
20632 for (
int y=1; y<h; ++y)
20633 memcpy(pixels.at(y), pixels.first(),
size_t(n)*
sizeof(QRgb));
20636 w =
rect().width();
20639 for (
int y=0; y<h; ++y)
20641 QRgb *pixels =
reinterpret_cast<QRgb*
>(
mGradientImage.scanLine(y));
20643 for (
int x=0; x<w; ++x)
20644 pixels[x] = lineColor;
20661 if (
QCPAxis *senderAxis = qobject_cast<QCPAxis*>(sender()))
20662 if (senderAxis->axisType() == type)
20686 if (
QCPAxis *senderAxis = qobject_cast<QCPAxis*>(sender()))
20687 if (senderAxis->axisType() == type)
20864 mAdaptiveSampling{}
20867 mParentPlot->registerGraph(
this);
20869 setPen(QPen(Qt::blue, 0));
20870 setBrush(Qt::NoBrush);
20872 setLineStyle(lsLine);
20874 setChannelFillGraph(
nullptr);
20875 setAdaptiveSampling(
true);
20916 addData(keys, values, alreadySorted);
20969 if (targetGraph ==
this)
20971 qDebug() << Q_FUNC_INFO <<
"targetGraph is this graph itself";
20978 qDebug() << Q_FUNC_INFO <<
"targetGraph not in same plot";
21036 if (keys.size() != values.size())
21037 qDebug() << Q_FUNC_INFO <<
"keys and values have different sizes:" << keys.size() << values.size();
21038 const int n = qMin(keys.size(), values.size());
21039 QVector<QCPGraphData> tempData(n);
21040 QVector<QCPGraphData>::iterator it = tempData.begin();
21041 const QVector<QCPGraphData>::iterator itEnd = tempData.end();
21043 while (it != itEnd)
21046 it->value = values[i];
21086 int pointIndex = int(closestDataPoint-
mDataContainer->constBegin());
21103 return mDataContainer->valueRange(foundRange, inSignDomain, inKeyRange);
21109 if (!
mKeyAxis || !
mValueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return; }
21113 QVector<QPointF> lines, scatters;
21116 QList<QCPDataRange> selectedSegments, unselectedSegments, allSegments;
21118 allSegments << unselectedSegments << selectedSegments;
21119 for (
int i=0; i<allSegments.size(); ++i)
21121 bool isSelectedSegment = i >= unselectedSegments.size();
21123 QCPDataRange lineDataRange = isSelectedSegment ? allSegments.at(i) : allSegments.at(i).
adjusted(-1, 1);
21127 #ifdef QCUSTOMPLOT_CHECK_DATA
21132 qDebug() << Q_FUNC_INFO <<
"Data point at" << it->key <<
"invalid." <<
"Plottable name:" <<
name();
21140 painter->setBrush(
mBrush);
21141 painter->
setPen(Qt::NoPen);
21151 painter->setBrush(Qt::NoBrush);
21162 if (!finalScatterStyle.
isNone())
21178 if (
mBrush.style() != Qt::NoBrush)
21181 painter->fillRect(QRectF(rect.left(), rect.top()+rect.height()/2.0, rect.width(), rect.height()/3.0),
mBrush);
21188 painter->
drawLine(QLineF(rect.left(), rect.top()+rect.height()/2.0, rect.right()+5, rect.top()+rect.height()/2.0));
21198 scaledStyle.
setPixmap(scaledStyle.
pixmap().scaled(rect.size().toSize(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
21200 scaledStyle.
drawShape(painter, QRectF(rect).center());
21231 if (!lines)
return;
21240 QVector<QCPGraphData> lineData;
21244 if (
mKeyAxis->rangeReversed() != (
mKeyAxis->orientation() == Qt::Vertical))
21245 std::reverse(lineData.begin(), lineData.end());
21249 case lsNone: lines->clear();
break;
21272 if (!scatters)
return;
21275 if (!
keyAxis || !
valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis"; scatters->clear();
return; }
21285 QVector<QCPGraphData>
data;
21288 if (
mKeyAxis->rangeReversed() != (
mKeyAxis->orientation() == Qt::Vertical))
21289 std::reverse(
data.begin(),
data.end());
21291 scatters->resize(
data.size());
21294 for (
int i=0; i<
data.size(); ++i)
21296 if (!qIsNaN(
data.at(i).value))
21304 for (
int i=0; i<
data.size(); ++i)
21306 if (!qIsNaN(
data.at(i).value))
21327 QVector<QPointF> result;
21330 if (!
keyAxis || !
valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return result; }
21332 result.resize(
data.size());
21337 for (
int i=0; i<
data.size(); ++i)
21344 for (
int i=0; i<
data.size(); ++i)
21365 QVector<QPointF> result;
21368 if (!
keyAxis || !
valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return result; }
21370 result.resize(
data.size()*2);
21376 for (
int i=0; i<
data.size(); ++i)
21379 result[i*2+0].setX(lastValue);
21380 result[i*2+0].setY(key);
21382 result[i*2+1].setX(lastValue);
21383 result[i*2+1].setY(key);
21388 for (
int i=0; i<
data.size(); ++i)
21391 result[i*2+0].setX(key);
21392 result[i*2+0].setY(lastValue);
21394 result[i*2+1].setX(key);
21395 result[i*2+1].setY(lastValue);
21413 QVector<QPointF> result;
21416 if (!
keyAxis || !
valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return result; }
21418 result.resize(
data.size()*2);
21424 for (
int i=0; i<
data.size(); ++i)
21427 result[i*2+0].setX(value);
21428 result[i*2+0].setY(lastKey);
21430 result[i*2+1].setX(value);
21431 result[i*2+1].setY(lastKey);
21436 for (
int i=0; i<
data.size(); ++i)
21439 result[i*2+0].setX(lastKey);
21440 result[i*2+0].setY(value);
21442 result[i*2+1].setX(lastKey);
21443 result[i*2+1].setY(value);
21461 QVector<QPointF> result;
21464 if (!
keyAxis || !
valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return result; }
21466 result.resize(
data.size()*2);
21473 result[0].setX(lastValue);
21474 result[0].setY(lastKey);
21475 for (
int i=1; i<
data.size(); ++i)
21478 result[i*2-1].setX(lastValue);
21479 result[i*2-1].setY(key);
21482 result[i*2+0].setX(lastValue);
21483 result[i*2+0].setY(key);
21485 result[
data.size()*2-1].setX(lastValue);
21486 result[
data.size()*2-1].setY(lastKey);
21491 result[0].setX(lastKey);
21492 result[0].setY(lastValue);
21493 for (
int i=1; i<
data.size(); ++i)
21496 result[i*2-1].setX(key);
21497 result[i*2-1].setY(lastValue);
21500 result[i*2+0].setX(key);
21501 result[i*2+0].setY(lastValue);
21503 result[
data.size()*2-1].setX(lastKey);
21504 result[
data.size()*2-1].setY(lastValue);
21521 QVector<QPointF> result;
21524 if (!
keyAxis || !
valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return result; }
21526 result.resize(
data.size()*2);
21531 for (
int i=0; i<
data.size(); ++i)
21535 result[i*2+0].setY(key);
21537 result[i*2+1].setY(key);
21541 for (
int i=0; i<
data.size(); ++i)
21544 result[i*2+0].setX(key);
21546 result[i*2+1].setX(key);
21573 if (painter->brush().style() == Qt::NoBrush || painter->brush().color().alpha() == 0)
return;
21585 QVector<QPointF> otherLines;
21587 if (!otherLines.isEmpty())
21590 QVector<QPair<QCPDataRange, QCPDataRange> > segmentPairs =
getOverlappingSegments(segments, lines, otherSegments, &otherLines);
21591 for (
int i=0; i<segmentPairs.size(); ++i)
21592 painter->drawPolygon(
getChannelFillPolygon(lines, segmentPairs.at(i).first, &otherLines, segmentPairs.at(i).second));
21608 foreach (
const QPointF &scatter, scatters)
21609 style.
drawShape(painter, scatter.x(), scatter.y());
21620 if (painter->pen().style() != Qt::NoPen && painter->pen().color().alpha() != 0)
21637 if (painter->pen().style() != Qt::NoPen && painter->pen().color().alpha() != 0)
21640 QPen oldPen = painter->pen();
21641 QPen newPen = painter->pen();
21642 newPen.setCapStyle(Qt::FlatCap);
21643 painter->
setPen(newPen);
21644 painter->drawLines(lines);
21645 painter->
setPen(oldPen);
21663 if (!lineData)
return;
21666 if (!
keyAxis || !
valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return; }
21667 if (begin == end)
return;
21670 int maxCount = (std::numeric_limits<int>::max)();
21674 if (2*keyPixelSpan+2 <
static_cast<double>((std::numeric_limits<int>::max)()))
21675 maxCount = int(2*keyPixelSpan+2);
21681 double minValue = it->value;
21682 double maxValue = it->value;
21685 int reversedRound = reversedFactor==-1 ? 1 : 0;
21687 double lastIntervalEndKey = currentIntervalStartKey;
21690 int intervalDataCount = 1;
21694 if (it->key < currentIntervalStartKey+keyEpsilon)
21696 if (it->value < minValue)
21697 minValue = it->value;
21698 else if (it->value > maxValue)
21699 maxValue = it->value;
21700 ++intervalDataCount;
21703 if (intervalDataCount >= 2)
21705 if (lastIntervalEndKey < currentIntervalStartKey-keyEpsilon)
21706 lineData->append(
QCPGraphData(currentIntervalStartKey+keyEpsilon*0.2, currentIntervalFirstPoint->value));
21707 lineData->append(
QCPGraphData(currentIntervalStartKey+keyEpsilon*0.25, minValue));
21708 lineData->append(
QCPGraphData(currentIntervalStartKey+keyEpsilon*0.75, maxValue));
21709 if (it->key > currentIntervalStartKey+keyEpsilon*2)
21710 lineData->append(
QCPGraphData(currentIntervalStartKey+keyEpsilon*0.8, (it-1)->value));
21712 lineData->append(
QCPGraphData(currentIntervalFirstPoint->key, currentIntervalFirstPoint->value));
21713 lastIntervalEndKey = (it-1)->key;
21714 minValue = it->value;
21715 maxValue = it->value;
21716 currentIntervalFirstPoint = it;
21718 if (keyEpsilonVariable)
21720 intervalDataCount = 1;
21725 if (intervalDataCount >= 2)
21727 if (lastIntervalEndKey < currentIntervalStartKey-keyEpsilon)
21728 lineData->append(
QCPGraphData(currentIntervalStartKey+keyEpsilon*0.2, currentIntervalFirstPoint->value));
21729 lineData->append(
QCPGraphData(currentIntervalStartKey+keyEpsilon*0.25, minValue));
21730 lineData->append(
QCPGraphData(currentIntervalStartKey+keyEpsilon*0.75, maxValue));
21732 lineData->append(
QCPGraphData(currentIntervalFirstPoint->key, currentIntervalFirstPoint->value));
21737 std::copy(begin, end, lineData->begin());
21755 if (!scatterData)
return;
21758 if (!
keyAxis || !
valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return; }
21764 while (doScatterSkip && begin != end && beginIndex % scatterModulo != 0)
21769 if (begin == end)
return;
21771 int maxCount = (std::numeric_limits<int>::max)();
21775 maxCount = 2*keyPixelSpan+2;
21783 int itIndex = int(beginIndex);
21784 double minValue = it->value;
21785 double maxValue = it->value;
21790 int reversedRound = reversedFactor==-1 ? 1 : 0;
21794 int intervalDataCount = 1;
21796 if (!doScatterSkip)
21800 itIndex += scatterModulo;
21801 if (itIndex < endIndex)
21802 it += scatterModulo;
21806 itIndex = endIndex;
21812 if (it->key < currentIntervalStartKey+keyEpsilon)
21814 if (it->value < minValue && it->value > valueMinRange && it->value < valueMaxRange)
21816 minValue = it->value;
21818 }
else if (it->value > maxValue && it->value > valueMinRange && it->value < valueMaxRange)
21820 maxValue = it->value;
21823 ++intervalDataCount;
21826 if (intervalDataCount >= 2)
21830 int dataModulo = qMax(1, qRound(intervalDataCount/(valuePixelSpan/4.0)));
21833 while (intervalIt != it)
21835 if ((c % dataModulo == 0 || intervalIt == minValueIt || intervalIt == maxValueIt) && intervalIt->value > valueMinRange && intervalIt->value < valueMaxRange)
21836 scatterData->append(*intervalIt);
21838 if (!doScatterSkip)
21841 intervalIt += scatterModulo;
21843 }
else if (currentIntervalStart->value > valueMinRange && currentIntervalStart->value < valueMaxRange)
21844 scatterData->append(*currentIntervalStart);
21845 minValue = it->value;
21846 maxValue = it->value;
21847 currentIntervalStart = it;
21849 if (keyEpsilonVariable)
21851 intervalDataCount = 1;
21854 if (!doScatterSkip)
21858 itIndex += scatterModulo;
21859 if (itIndex < endIndex)
21860 it += scatterModulo;
21864 itIndex = endIndex;
21869 if (intervalDataCount >= 2)
21873 int dataModulo = qMax(1, qRound(intervalDataCount/(valuePixelSpan/4.0)));
21875 int intervalItIndex = int(intervalIt-
mDataContainer->constBegin());
21877 while (intervalIt != it)
21879 if ((c % dataModulo == 0 || intervalIt == minValueIt || intervalIt == maxValueIt) && intervalIt->value > valueMinRange && intervalIt->value < valueMaxRange)
21880 scatterData->append(*intervalIt);
21882 if (!doScatterSkip)
21886 intervalItIndex += scatterModulo;
21887 if (intervalItIndex < itIndex)
21888 intervalIt += scatterModulo;
21892 intervalItIndex = itIndex;
21896 }
else if (currentIntervalStart->value > valueMinRange && currentIntervalStart->value < valueMaxRange)
21897 scatterData->append(*currentIntervalStart);
21902 int itIndex = beginIndex;
21906 scatterData->append(*it);
21908 if (!doScatterSkip)
21912 itIndex += scatterModulo;
21913 if (itIndex < endIndex)
21914 it += scatterModulo;
21918 itIndex = endIndex;
21936 if (rangeRestriction.
isEmpty())
21944 if (!
keyAxis || !
valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return; }
21949 mDataContainer->limitIteratorsToDataRange(begin, end, rangeRestriction);
21966 QVector<QCPDataRange> result;
21967 const int n = lineData->size();
21972 if (keyOrientation == Qt::Horizontal)
21976 while (i < n && qIsNaN(lineData->at(i).y()))
21981 while (i < n && !qIsNaN(lineData->at(i).y()))
21983 currentSegment.
setEnd(i++);
21984 result.append(currentSegment);
21990 while (i < n && qIsNaN(lineData->at(i).x()))
21995 while (i < n && !qIsNaN(lineData->at(i).x()))
21997 currentSegment.
setEnd(i++);
21998 result.append(currentSegment);
22022 QVector<QPair<QCPDataRange, QCPDataRange> >
QCPGraph::getOverlappingSegments(QVector<QCPDataRange> thisSegments,
const QVector<QPointF> *thisData, QVector<QCPDataRange> otherSegments,
const QVector<QPointF> *otherData)
const
22024 QVector<QPair<QCPDataRange, QCPDataRange> > result;
22025 if (thisData->isEmpty() || otherData->isEmpty() || thisSegments.isEmpty() || otherSegments.isEmpty())
22029 int otherIndex = 0;
22030 const bool verticalKey =
mKeyAxis->orientation() == Qt::Vertical;
22031 while (thisIndex < thisSegments.size() && otherIndex < otherSegments.size())
22033 if (thisSegments.at(thisIndex).size() < 2)
22038 if (otherSegments.at(otherIndex).size() < 2)
22043 double thisLower, thisUpper, otherLower, otherUpper;
22046 thisLower = thisData->at(thisSegments.at(thisIndex).begin()).x();
22047 thisUpper = thisData->at(thisSegments.at(thisIndex).end()-1).x();
22048 otherLower = otherData->at(otherSegments.at(otherIndex).begin()).x();
22049 otherUpper = otherData->at(otherSegments.at(otherIndex).end()-1).x();
22052 thisLower = thisData->at(thisSegments.at(thisIndex).begin()).y();
22053 thisUpper = thisData->at(thisSegments.at(thisIndex).end()-1).y();
22054 otherLower = otherData->at(otherSegments.at(otherIndex).begin()).y();
22055 otherUpper = otherData->at(otherSegments.at(otherIndex).end()-1).y();
22059 if (
segmentsIntersect(thisLower, thisUpper, otherLower, otherUpper, bPrecedence))
22060 result.append(QPair<QCPDataRange, QCPDataRange>(thisSegments.at(thisIndex), otherSegments.at(otherIndex)));
22062 if (bPrecedence <= 0)
22088 if (aLower > bUpper)
22092 }
else if (bLower > aUpper)
22098 if (aUpper > bUpper)
22100 else if (aUpper < bUpper)
22122 if (!
keyAxis || !
valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return {}; }
22129 result.setX(matchingDataPoint.x());
22134 result.setY(matchingDataPoint.y());
22147 result.setY(matchingDataPoint.y());
22150 result.setX(matchingDataPoint.x());
22179 if (segment.
size() < 2)
22180 return QPolygonF();
22181 QPolygonF result(segment.
size()+2);
22184 std::copy(lineData->constBegin()+segment.
begin(), lineData->constBegin()+segment.
end(), result.begin()+1);
22211 return QPolygonF();
22215 if (!
keyAxis || !
valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return QPolygonF(); }
22216 if (!
mChannelFillGraph.data()->mKeyAxis) { qDebug() << Q_FUNC_INFO <<
"channel fill target key axis invalid";
return QPolygonF(); }
22219 return QPolygonF();
22221 if (thisData->isEmpty())
return QPolygonF();
22222 QVector<QPointF> thisSegmentData(thisSegment.
size());
22223 QVector<QPointF> otherSegmentData(otherSegment.
size());
22224 std::copy(thisData->constBegin()+thisSegment.
begin(), thisData->constBegin()+thisSegment.
end(), thisSegmentData.begin());
22225 std::copy(otherData->constBegin()+otherSegment.
begin(), otherData->constBegin()+otherSegment.
end(), otherSegmentData.begin());
22227 QVector<QPointF> *staticData = &thisSegmentData;
22228 QVector<QPointF> *croppedData = &otherSegmentData;
22235 if (staticData->first().x() < croppedData->first().x())
22236 qSwap(staticData, croppedData);
22237 const int lowBound =
findIndexBelowX(croppedData, staticData->first().x());
22238 if (lowBound == -1)
return QPolygonF();
22239 croppedData->remove(0, lowBound);
22241 if (croppedData->size() < 2)
return QPolygonF();
22243 if (!qFuzzyCompare(croppedData->at(1).x(), croppedData->at(0).x()))
22244 slope = (croppedData->at(1).y()-croppedData->at(0).y())/(croppedData->at(1).x()-croppedData->at(0).x());
22247 (*croppedData)[0].setY(croppedData->at(0).y()+slope*(staticData->first().x()-croppedData->at(0).x()));
22248 (*croppedData)[0].setX(staticData->first().x());
22251 if (staticData->last().x() > croppedData->last().x())
22252 qSwap(staticData, croppedData);
22253 int highBound =
findIndexAboveX(croppedData, staticData->last().x());
22254 if (highBound == -1)
return QPolygonF();
22255 croppedData->remove(highBound+1, croppedData->size()-(highBound+1));
22257 if (croppedData->size() < 2)
return QPolygonF();
22258 const int li = croppedData->size()-1;
22259 if (!qFuzzyCompare(croppedData->at(li).x(), croppedData->at(li-1).x()))
22260 slope = (croppedData->at(li).y()-croppedData->at(li-1).y())/(croppedData->at(li).x()-croppedData->at(li-1).x());
22263 (*croppedData)[li].setY(croppedData->at(li-1).y()+slope*(staticData->last().x()-croppedData->at(li-1).x()));
22264 (*croppedData)[li].setX(staticData->last().x());
22269 if (staticData->first().y() < croppedData->first().y())
22270 qSwap(staticData, croppedData);
22271 int lowBound =
findIndexBelowY(croppedData, staticData->first().y());
22272 if (lowBound == -1)
return QPolygonF();
22273 croppedData->remove(0, lowBound);
22275 if (croppedData->size() < 2)
return QPolygonF();
22277 if (!qFuzzyCompare(croppedData->at(1).y(), croppedData->at(0).y()))
22278 slope = (croppedData->at(1).x()-croppedData->at(0).x())/(croppedData->at(1).y()-croppedData->at(0).y());
22281 (*croppedData)[0].setX(croppedData->at(0).x()+slope*(staticData->first().y()-croppedData->at(0).y()));
22282 (*croppedData)[0].setY(staticData->first().y());
22285 if (staticData->last().y() > croppedData->last().y())
22286 qSwap(staticData, croppedData);
22287 int highBound =
findIndexAboveY(croppedData, staticData->last().y());
22288 if (highBound == -1)
return QPolygonF();
22289 croppedData->remove(highBound+1, croppedData->size()-(highBound+1));
22291 if (croppedData->size() < 2)
return QPolygonF();
22292 int li = croppedData->size()-1;
22293 if (!qFuzzyCompare(croppedData->at(li).y(), croppedData->at(li-1).y()))
22294 slope = (croppedData->at(li).x()-croppedData->at(li-1).x())/(croppedData->at(li).y()-croppedData->at(li-1).y());
22297 (*croppedData)[li].setX(croppedData->at(li-1).x()+slope*(staticData->last().y()-croppedData->at(li-1).y()));
22298 (*croppedData)[li].setY(staticData->last().y());
22302 for (
int i=otherSegmentData.size()-1; i>=0; --i)
22303 thisSegmentData << otherSegmentData.at(i);
22304 return QPolygonF(thisSegmentData);
22317 for (
int i=
data->size()-1; i>=0; --i)
22319 if (
data->at(i).x() < x)
22321 if (i<data->size()-1)
22324 return data->size()-1;
22340 for (
int i=0; i<
data->size(); ++i)
22342 if (
data->at(i).x() > x)
22363 for (
int i=
data->size()-1; i>=0; --i)
22365 if (
data->at(i).y() < y)
22367 if (i<data->size()-1)
22370 return data->size()-1;
22396 double minDistSqr = (std::numeric_limits<double>::max)();
22398 double posKeyMin, posKeyMax, dummy;
22401 if (posKeyMin > posKeyMax)
22402 qSwap(posKeyMin, posKeyMax);
22409 if (currentDistSqr < minDistSqr)
22411 minDistSqr = currentDistSqr;
22420 QVector<QPointF> lineData;
22424 for (
int i=0; i<lineData.size()-1; i+=step)
22427 if (currentDistSqr < minDistSqr)
22428 minDistSqr = currentDistSqr;
22432 return qSqrt(minDistSqr);
22445 for (
int i=0; i<
data->size(); ++i)
22447 if (
data->at(i).y() > y)
22624 setPen(QPen(Qt::blue, 0));
22625 setBrush(Qt::NoBrush);
22628 setLineStyle(lsLine);
22667 void QCPCurve::setData(
const QVector<double> &t,
const QVector<double> &keys,
const QVector<double> &values,
bool alreadySorted)
22670 addData(t, keys, values, alreadySorted);
22743 void QCPCurve::addData(
const QVector<double> &t,
const QVector<double> &keys,
const QVector<double> &values,
bool alreadySorted)
22745 if (t.size() != keys.size() || t.size() != values.size())
22746 qDebug() << Q_FUNC_INFO <<
"ts, keys and values have different sizes:" << t.size() << keys.size() << values.size();
22747 const int n = qMin(qMin(t.size(), keys.size()), values.size());
22748 QVector<QCPCurveData> tempData(n);
22749 QVector<QCPCurveData>::iterator it = tempData.begin();
22750 const QVector<QCPCurveData>::iterator itEnd = tempData.end();
22752 while (it != itEnd)
22756 it->value = values[i];
22777 if (keys.size() != values.size())
22778 qDebug() << Q_FUNC_INFO <<
"keys and values have different sizes:" << keys.size() << values.size();
22779 const int n = qMin(keys.size(), values.size());
22785 QVector<QCPCurveData> tempData(n);
22786 QVector<QCPCurveData>::iterator it = tempData.begin();
22787 const QVector<QCPCurveData>::iterator itEnd = tempData.end();
22789 while (it != itEnd)
22791 it->t = tStart + i;
22793 it->value = values[i];
22850 int pointIndex = int( closestDataPoint-
mDataContainer->constBegin() );
22867 return mDataContainer->valueRange(foundRange, inSignDomain, inKeyRange);
22876 QVector<QPointF> lines, scatters;
22879 QList<QCPDataRange> selectedSegments, unselectedSegments, allSegments;
22881 allSegments << unselectedSegments << selectedSegments;
22882 for (
int i=0; i<allSegments.size(); ++i)
22884 bool isSelectedSegment = i >= unselectedSegments.size();
22887 QPen finalCurvePen =
mPen;
22891 QCPDataRange lineDataRange = isSelectedSegment ? allSegments.at(i) : allSegments.at(i).
adjusted(-1, 1);
22892 getCurveLines(&lines, lineDataRange, finalCurvePen.widthF());
22895 #ifdef QCUSTOMPLOT_CHECK_DATA
22900 qDebug() << Q_FUNC_INFO <<
"Data point at" << it->key <<
"invalid." <<
"Plottable name:" <<
name();
22909 painter->setBrush(
mBrush);
22910 painter->
setPen(Qt::NoPen);
22911 if (painter->brush().style() != Qt::NoBrush && painter->brush().color().alpha() != 0)
22912 painter->drawPolygon(QPolygonF(lines));
22917 painter->
setPen(finalCurvePen);
22918 painter->setBrush(Qt::NoBrush);
22926 if (!finalScatterStyle.
isNone())
22942 if (
mBrush.style() != Qt::NoBrush)
22945 painter->fillRect(QRectF(rect.left(), rect.top()+rect.height()/2.0, rect.width(), rect.height()/3.0),
mBrush);
22952 painter->
drawLine(QLineF(rect.left(), rect.top()+rect.height()/2.0, rect.right()+5, rect.top()+rect.height()/2.0));
22962 scaledStyle.
setPixmap(scaledStyle.
pixmap().scaled(rect.size().toSize(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
22964 scaledStyle.
drawShape(painter, QRectF(rect).center());
22981 if (painter->pen().style() != Qt::NoPen && painter->pen().color().alpha() != 0)
23000 foreach (
const QPointF &point, points)
23001 if (!qIsNaN(point.x()) && !qIsNaN(point.y()))
23035 if (!lines)
return;
23039 if (!
keyAxis || !
valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return; }
23042 const double strokeMargin = qMax(qreal(1.0), qreal(penWidth*0.75));
23049 mDataContainer->limitIteratorsToDataRange(itBegin, itEnd, dataRange);
23050 if (itBegin == itEnd)
23054 int prevRegion =
getRegion(prevIt->key, prevIt->value, keyMin, valueMax, keyMax, valueMin);
23055 QVector<QPointF> trailingPoints;
23056 while (it != itEnd)
23058 const int currentRegion =
getRegion(it->key, it->value, keyMin, valueMax, keyMax, valueMin);
23059 if (currentRegion != prevRegion)
23061 if (currentRegion != 5)
23063 QPointF crossA, crossB;
23064 if (prevRegion == 5)
23066 lines->append(
getOptimizedPoint(currentRegion, it->key, it->value, prevIt->key, prevIt->value, keyMin, valueMax, keyMax, valueMin));
23068 *lines <<
getOptimizedCornerPoints(prevRegion, currentRegion, prevIt->key, prevIt->value, it->key, it->value, keyMin, valueMax, keyMax, valueMin);
23069 }
else if (
mayTraverse(prevRegion, currentRegion) &&
23070 getTraverse(prevIt->key, prevIt->value, it->key, it->value, keyMin, valueMax, keyMax, valueMin, crossA, crossB))
23073 QVector<QPointF> beforeTraverseCornerPoints, afterTraverseCornerPoints;
23074 getTraverseCornerPoints(prevRegion, currentRegion, keyMin, valueMax, keyMax, valueMin, beforeTraverseCornerPoints, afterTraverseCornerPoints);
23077 *lines << beforeTraverseCornerPoints;
23078 lines->append(crossA);
23079 lines->append(crossB);
23080 *lines << afterTraverseCornerPoints;
23083 lines->append(crossB);
23084 *lines << afterTraverseCornerPoints;
23085 trailingPoints << beforeTraverseCornerPoints << crossA ;
23089 *lines <<
getOptimizedCornerPoints(prevRegion, currentRegion, prevIt->key, prevIt->value, it->key, it->value, keyMin, valueMax, keyMax, valueMin);
23094 trailingPoints <<
getOptimizedPoint(prevRegion, prevIt->key, prevIt->value, it->key, it->value, keyMin, valueMax, keyMax, valueMin);
23096 lines->append(
getOptimizedPoint(prevRegion, prevIt->key, prevIt->value, it->key, it->value, keyMin, valueMax, keyMax, valueMin));
23101 if (currentRegion == 5)
23110 prevRegion = currentRegion;
23113 *lines << trailingPoints;
23138 if (!scatters)
return;
23142 if (!
keyAxis || !
valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return; }
23146 mDataContainer->limitIteratorsToDataRange(begin, end, dataRange);
23163 while (doScatterSkip && it != end && itIndex % scatterModulo != 0)
23172 if (!qIsNaN(it->value) && keyRange.
contains(it->key) && valueRange.
contains(it->value))
23176 if (!doScatterSkip)
23180 itIndex += scatterModulo;
23181 if (itIndex < endIndex)
23182 it += scatterModulo;
23186 itIndex = endIndex;
23194 if (!qIsNaN(it->value) && keyRange.
contains(it->key) && valueRange.
contains(it->value))
23198 if (!doScatterSkip)
23202 itIndex += scatterModulo;
23203 if (itIndex < endIndex)
23204 it += scatterModulo;
23208 itIndex = endIndex;
23234 int QCPCurve::getRegion(
double key,
double value,
double keyMin,
double valueMax,
double keyMax,
double valueMin)
const
23238 if (value > valueMax)
23240 else if (value < valueMin)
23244 }
else if (key > keyMax)
23246 if (value > valueMax)
23248 else if (value < valueMin)
23254 if (value > valueMax)
23256 else if (value < valueMin)
23278 QPointF
QCPCurve::getOptimizedPoint(
int otherRegion,
double otherKey,
double otherValue,
double key,
double value,
double keyMin,
double valueMax,
double keyMax,
double valueMin)
const
23285 const double keyMinPx =
mKeyAxis->coordToPixel(keyMin);
23286 const double keyMaxPx =
mKeyAxis->coordToPixel(keyMax);
23287 const double valueMinPx =
mValueAxis->coordToPixel(valueMin);
23288 const double valueMaxPx =
mValueAxis->coordToPixel(valueMax);
23289 const double otherValuePx =
mValueAxis->coordToPixel(otherValue);
23290 const double valuePx =
mValueAxis->coordToPixel(value);
23291 const double otherKeyPx =
mKeyAxis->coordToPixel(otherKey);
23292 const double keyPx =
mKeyAxis->coordToPixel(key);
23293 double intersectKeyPx = keyMinPx;
23294 double intersectValuePx = valueMinPx;
23295 switch (otherRegion)
23299 intersectValuePx = valueMaxPx;
23300 intersectKeyPx = otherKeyPx + (keyPx-otherKeyPx)/(valuePx-otherValuePx)*(intersectValuePx-otherValuePx);
23301 if (intersectKeyPx < qMin(keyMinPx, keyMaxPx) || intersectKeyPx > qMax(keyMinPx, keyMaxPx))
23303 intersectKeyPx = keyMinPx;
23304 intersectValuePx = otherValuePx + (valuePx-otherValuePx)/(keyPx-otherKeyPx)*(intersectKeyPx-otherKeyPx);
23310 intersectKeyPx = keyMinPx;
23311 intersectValuePx = otherValuePx + (valuePx-otherValuePx)/(keyPx-otherKeyPx)*(intersectKeyPx-otherKeyPx);
23316 intersectValuePx = valueMinPx;
23317 intersectKeyPx = otherKeyPx + (keyPx-otherKeyPx)/(valuePx-otherValuePx)*(intersectValuePx-otherValuePx);
23318 if (intersectKeyPx < qMin(keyMinPx, keyMaxPx) || intersectKeyPx > qMax(keyMinPx, keyMaxPx))
23320 intersectKeyPx = keyMinPx;
23321 intersectValuePx = otherValuePx + (valuePx-otherValuePx)/(keyPx-otherKeyPx)*(intersectKeyPx-otherKeyPx);
23327 intersectValuePx = valueMaxPx;
23328 intersectKeyPx = otherKeyPx + (keyPx-otherKeyPx)/(valuePx-otherValuePx)*(intersectValuePx-otherValuePx);
23337 intersectValuePx = valueMinPx;
23338 intersectKeyPx = otherKeyPx + (keyPx-otherKeyPx)/(valuePx-otherValuePx)*(intersectValuePx-otherValuePx);
23343 intersectValuePx = valueMaxPx;
23344 intersectKeyPx = otherKeyPx + (keyPx-otherKeyPx)/(valuePx-otherValuePx)*(intersectValuePx-otherValuePx);
23345 if (intersectKeyPx < qMin(keyMinPx, keyMaxPx) || intersectKeyPx > qMax(keyMinPx, keyMaxPx))
23347 intersectKeyPx = keyMaxPx;
23348 intersectValuePx = otherValuePx + (valuePx-otherValuePx)/(keyPx-otherKeyPx)*(intersectKeyPx-otherKeyPx);
23354 intersectKeyPx = keyMaxPx;
23355 intersectValuePx = otherValuePx + (valuePx-otherValuePx)/(keyPx-otherKeyPx)*(intersectKeyPx-otherKeyPx);
23360 intersectValuePx = valueMinPx;
23361 intersectKeyPx = otherKeyPx + (keyPx-otherKeyPx)/(valuePx-otherValuePx)*(intersectValuePx-otherValuePx);
23362 if (intersectKeyPx < qMin(keyMinPx, keyMaxPx) || intersectKeyPx > qMax(keyMinPx, keyMaxPx))
23364 intersectKeyPx = keyMaxPx;
23365 intersectValuePx = otherValuePx + (valuePx-otherValuePx)/(keyPx-otherKeyPx)*(intersectKeyPx-otherKeyPx);
23370 if (
mKeyAxis->orientation() == Qt::Horizontal)
23371 return {intersectKeyPx, intersectValuePx};
23373 return {intersectValuePx, intersectKeyPx};
23394 QVector<QPointF>
QCPCurve::getOptimizedCornerPoints(
int prevRegion,
int currentRegion,
double prevKey,
double prevValue,
double key,
double value,
double keyMin,
double valueMax,
double keyMax,
double valueMin)
const
23396 QVector<QPointF> result;
23397 switch (prevRegion)
23401 switch (currentRegion)
23410 if ((value-prevValue)/(key-prevKey)*(keyMin-key)+value < valueMin)
23421 switch (currentRegion)
23425 case 4: { result <<
coordsToPixels(keyMin, valueMax); result.append(result.last());
break; }
23426 case 6: { result <<
coordsToPixels(keyMin, valueMin); result.append(result.last());
break; }
23427 case 7: { result <<
coordsToPixels(keyMin, valueMax); result.append(result.last()); result <<
coordsToPixels(keyMax, valueMax);
break; }
23428 case 9: { result <<
coordsToPixels(keyMin, valueMin); result.append(result.last()); result <<
coordsToPixels(keyMax, valueMin);
break; }
23434 switch (currentRegion)
23443 if ((value-prevValue)/(key-prevKey)*(keyMax-key)+value < valueMin)
23454 switch (currentRegion)
23458 case 2: { result <<
coordsToPixels(keyMin, valueMax); result.append(result.last());
break; }
23459 case 8: { result <<
coordsToPixels(keyMax, valueMax); result.append(result.last());
break; }
23460 case 3: { result <<
coordsToPixels(keyMin, valueMax); result.append(result.last()); result <<
coordsToPixels(keyMin, valueMin);
break; }
23461 case 9: { result <<
coordsToPixels(keyMax, valueMax); result.append(result.last()); result <<
coordsToPixels(keyMax, valueMin);
break; }
23467 switch (currentRegion)
23478 switch (currentRegion)
23482 case 2: { result <<
coordsToPixels(keyMin, valueMin); result.append(result.last());
break; }
23483 case 8: { result <<
coordsToPixels(keyMax, valueMin); result.append(result.last());
break; }
23484 case 1: { result <<
coordsToPixels(keyMin, valueMin); result.append(result.last()); result <<
coordsToPixels(keyMin, valueMax);
break; }
23485 case 7: { result <<
coordsToPixels(keyMax, valueMin); result.append(result.last()); result <<
coordsToPixels(keyMax, valueMax);
break; }
23491 switch (currentRegion)
23500 if ((value-prevValue)/(key-prevKey)*(keyMax-key)+value < valueMin)
23511 switch (currentRegion)
23515 case 4: { result <<
coordsToPixels(keyMax, valueMax); result.append(result.last());
break; }
23516 case 6: { result <<
coordsToPixels(keyMax, valueMin); result.append(result.last());
break; }
23517 case 1: { result <<
coordsToPixels(keyMax, valueMax); result.append(result.last()); result <<
coordsToPixels(keyMin, valueMax);
break; }
23518 case 3: { result <<
coordsToPixels(keyMax, valueMin); result.append(result.last()); result <<
coordsToPixels(keyMin, valueMin);
break; }
23524 switch (currentRegion)
23533 if ((value-prevValue)/(key-prevKey)*(keyMin-key)+value < valueMin)
23560 switch (prevRegion)
23564 switch (currentRegion)
23569 case 3:
return false;
23570 default:
return true;
23575 switch (currentRegion)
23578 case 3:
return false;
23579 default:
return true;
23584 switch (currentRegion)
23589 case 9:
return false;
23590 default:
return true;
23595 switch (currentRegion)
23598 case 7:
return false;
23599 default:
return true;
23602 case 5:
return false;
23605 switch (currentRegion)
23608 case 9:
return false;
23609 default:
return true;
23614 switch (currentRegion)
23619 case 9:
return false;
23620 default:
return true;
23625 switch (currentRegion)
23628 case 9:
return false;
23629 default:
return true;
23634 switch (currentRegion)
23639 case 7:
return false;
23640 default:
return true;
23643 default:
return true;
23661 bool QCPCurve::getTraverse(
double prevKey,
double prevValue,
double key,
double value,
double keyMin,
double valueMax,
double keyMax,
double valueMin, QPointF &crossA, QPointF &crossB)
const
23668 QList<QPointF> intersections;
23669 const double valueMinPx =
mValueAxis->coordToPixel(valueMin);
23670 const double valueMaxPx =
mValueAxis->coordToPixel(valueMax);
23671 const double keyMinPx =
mKeyAxis->coordToPixel(keyMin);
23672 const double keyMaxPx =
mKeyAxis->coordToPixel(keyMax);
23673 const double keyPx =
mKeyAxis->coordToPixel(key);
23674 const double valuePx =
mValueAxis->coordToPixel(value);
23675 const double prevKeyPx =
mKeyAxis->coordToPixel(prevKey);
23676 const double prevValuePx =
mValueAxis->coordToPixel(prevValue);
23677 if (qFuzzyIsNull(keyPx-prevKeyPx))
23680 intersections.append(
mKeyAxis->orientation() == Qt::Horizontal ? QPointF(keyPx, valueMinPx) : QPointF(valueMinPx, keyPx));
23681 intersections.append(
mKeyAxis->orientation() == Qt::Horizontal ? QPointF(keyPx, valueMaxPx) : QPointF(valueMaxPx, keyPx));
23682 }
else if (qFuzzyIsNull(valuePx-prevValuePx))
23685 intersections.append(
mKeyAxis->orientation() == Qt::Horizontal ? QPointF(keyMinPx, valuePx) : QPointF(valuePx, keyMinPx));
23686 intersections.append(
mKeyAxis->orientation() == Qt::Horizontal ? QPointF(keyMaxPx, valuePx) : QPointF(valuePx, keyMaxPx));
23690 double keyPerValuePx = (keyPx-prevKeyPx)/(valuePx-prevValuePx);
23692 gamma = prevKeyPx + (valueMaxPx-prevValuePx)*keyPerValuePx;
23693 if (gamma >= qMin(keyMinPx, keyMaxPx) && gamma <= qMax(keyMinPx, keyMaxPx))
23694 intersections.append(
mKeyAxis->orientation() == Qt::Horizontal ? QPointF(gamma, valueMaxPx) : QPointF(valueMaxPx, gamma));
23696 gamma = prevKeyPx + (valueMinPx-prevValuePx)*keyPerValuePx;
23697 if (gamma >= qMin(keyMinPx, keyMaxPx) && gamma <= qMax(keyMinPx, keyMaxPx))
23698 intersections.append(
mKeyAxis->orientation() == Qt::Horizontal ? QPointF(gamma, valueMinPx) : QPointF(valueMinPx, gamma));
23699 const double valuePerKeyPx = 1.0/keyPerValuePx;
23701 gamma = prevValuePx + (keyMinPx-prevKeyPx)*valuePerKeyPx;
23702 if (gamma >= qMin(valueMinPx, valueMaxPx) && gamma <= qMax(valueMinPx, valueMaxPx))
23703 intersections.append(
mKeyAxis->orientation() == Qt::Horizontal ? QPointF(keyMinPx, gamma) : QPointF(gamma, keyMinPx));
23705 gamma = prevValuePx + (keyMaxPx-prevKeyPx)*valuePerKeyPx;
23706 if (gamma >= qMin(valueMinPx, valueMaxPx) && gamma <= qMax(valueMinPx, valueMaxPx))
23707 intersections.append(
mKeyAxis->orientation() == Qt::Horizontal ? QPointF(keyMaxPx, gamma) : QPointF(gamma, keyMaxPx));
23711 if (intersections.size() > 2)
23714 double distSqrMax = 0;
23716 for (
int i=0; i<intersections.size()-1; ++i)
23718 for (
int k=i+1; k<intersections.size(); ++k)
23720 QPointF distPoint = intersections.at(i)-intersections.at(k);
23721 double distSqr = distPoint.x()*distPoint.x()+distPoint.y()+distPoint.y();
23722 if (distSqr > distSqrMax)
23724 pv1 = intersections.at(i);
23725 pv2 = intersections.at(k);
23726 distSqrMax = distSqr;
23730 intersections = QList<QPointF>() << pv1 << pv2;
23731 }
else if (intersections.size() != 2)
23738 double xDelta = keyPx-prevKeyPx;
23739 double yDelta = valuePx-prevValuePx;
23740 if (
mKeyAxis->orientation() != Qt::Horizontal)
23741 qSwap(xDelta, yDelta);
23742 if (xDelta*(intersections.at(1).x()-intersections.at(0).x()) + yDelta*(intersections.at(1).y()-intersections.at(0).y()) < 0)
23743 intersections.move(0, 1);
23744 crossA = intersections.at(0);
23745 crossB = intersections.at(1);
23774 void QCPCurve::getTraverseCornerPoints(
int prevRegion,
int currentRegion,
double keyMin,
double valueMax,
double keyMax,
double valueMin, QVector<QPointF> &beforeTraverse, QVector<QPointF> &afterTraverse)
const
23776 switch (prevRegion)
23780 switch (currentRegion)
23782 case 6: { beforeTraverse <<
coordsToPixels(keyMin, valueMax);
break; }
23784 case 8: { beforeTraverse <<
coordsToPixels(keyMin, valueMax);
break; }
23790 switch (currentRegion)
23792 case 7: { afterTraverse <<
coordsToPixels(keyMax, valueMax);
break; }
23793 case 9: { afterTraverse <<
coordsToPixels(keyMax, valueMin);
break; }
23799 switch (currentRegion)
23801 case 4: { beforeTraverse <<
coordsToPixels(keyMin, valueMin);
break; }
23803 case 8: { beforeTraverse <<
coordsToPixels(keyMin, valueMin);
break; }
23809 switch (currentRegion)
23811 case 3: { afterTraverse <<
coordsToPixels(keyMin, valueMin);
break; }
23812 case 9: { afterTraverse <<
coordsToPixels(keyMax, valueMin);
break; }
23819 switch (currentRegion)
23821 case 1: { afterTraverse <<
coordsToPixels(keyMin, valueMax);
break; }
23822 case 7: { afterTraverse <<
coordsToPixels(keyMax, valueMax);
break; }
23828 switch (currentRegion)
23830 case 2: { beforeTraverse <<
coordsToPixels(keyMax, valueMax);
break; }
23832 case 6: { beforeTraverse <<
coordsToPixels(keyMax, valueMax);
break; }
23838 switch (currentRegion)
23840 case 1: { afterTraverse <<
coordsToPixels(keyMin, valueMax);
break; }
23841 case 3: { afterTraverse <<
coordsToPixels(keyMin, valueMin);
break; }
23847 switch (currentRegion)
23849 case 2: { beforeTraverse <<
coordsToPixels(keyMax, valueMin);
break; }
23851 case 4: { beforeTraverse <<
coordsToPixels(keyMax, valueMin);
break; }
23886 double minDistSqr = (std::numeric_limits<double>::max)();
23893 if (currentDistSqr < minDistSqr)
23895 minDistSqr = currentDistSqr;
23903 QVector<QPointF> lines;
23905 for (
int i=0; i<lines.size()-1; ++i)
23908 if (currentDistSqr < minDistSqr)
23909 minDistSqr = currentDistSqr;
23913 return qSqrt(minDistSqr);
23994 QObject(parentPlot),
23995 mParentPlot(parentPlot),
23996 mSpacingType(stAbsolute),
24037 if (index >= 0 && index <
mBars.size())
24039 return mBars.at(index);
24042 qDebug() << Q_FUNC_INFO <<
"index out of bounds:" << index;
24054 const QList<QCPBars*> oldBars =
mBars;
24056 bars->setBarsGroup(
nullptr);
24069 qDebug() << Q_FUNC_INFO <<
"bars is 0";
24074 bars->setBarsGroup(
this);
24076 qDebug() << Q_FUNC_INFO <<
"bars plottable is already in this bars group:" <<
reinterpret_cast<quintptr
>(
bars);
24092 qDebug() << Q_FUNC_INFO <<
"bars is 0";
24098 bars->setBarsGroup(
this);
24112 qDebug() << Q_FUNC_INFO <<
"bars is 0";
24117 bars->setBarsGroup(
nullptr);
24119 qDebug() << Q_FUNC_INFO <<
"bars plottable is not in this bars group:" <<
reinterpret_cast<quintptr
>(
bars);
24156 QList<const QCPBars*> baseBars;
24161 if (!baseBars.contains(b))
24162 baseBars.append(b);
24171 int index = baseBars.indexOf(thisBase);
24174 if (baseBars.size() % 2 == 1 && index == (baseBars.size()-1)/2)
24179 double lowerPixelWidth, upperPixelWidth;
24181 int dir = (index <= (baseBars.size()-1)/2) ? -1 : 1;
24182 if (baseBars.size() % 2 == 0)
24184 startIndex = baseBars.size()/2 + (dir < 0 ? -1 : 0);
24188 startIndex = (baseBars.size()-1)/2+dir;
24189 baseBars.at((baseBars.size()-1)/2)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth);
24190 result += qAbs(upperPixelWidth-lowerPixelWidth)*0.5;
24191 result +=
getPixelSpacing(baseBars.at((baseBars.size()-1)/2), keyCoord);
24193 for (
int i = startIndex; i != index; i += dir)
24195 baseBars.at(i)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth);
24196 result += qAbs(upperPixelWidth-lowerPixelWidth);
24200 baseBars.at(index)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth);
24201 result += qAbs(upperPixelWidth-lowerPixelWidth)*0.5;
24229 if (
bars->keyAxis()->orientation() == Qt::Horizontal)
24232 return bars->keyAxis()->axisRect()->height()*
mSpacing;
24236 double keyPixel =
bars->keyAxis()->coordToPixel(keyCoord);
24237 return qAbs(
bars->keyAxis()->coordToPixel(keyCoord+
mSpacing)-keyPixel);
24411 mWidthType(wtPlotCoords),
24412 mBarsGroup(nullptr),
24417 mPen.setColor(Qt::blue);
24418 mPen.setStyle(Qt::SolidLine);
24419 mBrush.setColor(QColor(40, 50, 255, 30));
24420 mBrush.setStyle(Qt::SolidPattern);
24462 void QCPBars::setData(
const QVector<double> &keys,
const QVector<double> &values,
bool alreadySorted)
24465 addData(keys, values, alreadySorted);
24548 void QCPBars::addData(
const QVector<double> &keys,
const QVector<double> &values,
bool alreadySorted)
24550 if (keys.size() != values.size())
24551 qDebug() << Q_FUNC_INFO <<
"keys and values have different sizes:" << keys.size() << values.size();
24552 const int n = qMin(keys.size(), values.size());
24553 QVector<QCPBarsData> tempData(n);
24554 QVector<QCPBarsData>::iterator it = tempData.begin();
24555 const QVector<QCPBarsData>::iterator itEnd = tempData.end();
24557 while (it != itEnd)
24560 it->value = values[i];
24594 if (bars ==
this)
return;
24597 qDebug() << Q_FUNC_INFO <<
"passed QCPBars* doesn't have same key and value axis as this QCPBars";
24627 if (bars ==
this)
return;
24630 qDebug() << Q_FUNC_INFO <<
"passed QCPBars* doesn't have same key and value axis as this QCPBars";
24660 if (rect.intersects(
getBarRect(it->key, it->value)))
24690 if (
getBarRect(it->key, it->value).contains(pos))
24722 double lowerPixelWidth, upperPixelWidth, keyPixel;
24725 keyPixel =
mKeyAxis.data()->coordToPixel(range.
lower) + lowerPixelWidth;
24728 const double lowerCorrected =
mKeyAxis.data()->pixelToCoord(keyPixel);
24729 if (!qIsNaN(lowerCorrected) && qIsFinite(lowerCorrected) && range.
lower > lowerCorrected)
24730 range.
lower = lowerCorrected;
24733 keyPixel =
mKeyAxis.data()->coordToPixel(range.
upper) + upperPixelWidth;
24736 const double upperCorrected =
mKeyAxis.data()->pixelToCoord(keyPixel);
24737 if (!qIsNaN(upperCorrected) && qIsFinite(upperCorrected) && range.
upper < upperCorrected)
24738 range.
upper = upperCorrected;
24751 bool haveLower =
true;
24752 bool haveUpper =
true;
24763 if (qIsNaN(current))
continue;
24766 if (current < range.
lower || !haveLower)
24768 range.
lower = current;
24771 if (current > range.
upper || !haveUpper)
24773 range.
upper = current;
24786 if (index >= 0 && index < mDataContainer->size())
24790 if (!
keyAxis || !
valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return {}; }
24796 return {keyPixel, valuePixel};
24798 return {valuePixel, keyPixel};
24801 qDebug() << Q_FUNC_INFO <<
"Index out of bounds" << index;
24809 if (!
mKeyAxis || !
mValueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return; }
24816 QList<QCPDataRange> selectedSegments, unselectedSegments, allSegments;
24818 allSegments << unselectedSegments << selectedSegments;
24819 for (
int i=0; i<allSegments.size(); ++i)
24821 bool isSelectedSegment = i >= unselectedSegments.size();
24824 mDataContainer->limitIteratorsToDataRange(begin, end, allSegments.at(i));
24831 #ifdef QCUSTOMPLOT_CHECK_DATA
24833 qDebug() << Q_FUNC_INFO <<
"Data point at" << it->key <<
"of drawn range invalid." <<
"Plottable name:" <<
name();
24842 painter->setBrush(
mBrush);
24846 painter->drawPolygon(
getBarRect(it->key, it->value));
24860 painter->setBrush(
mBrush);
24862 QRectF r = QRectF(0, 0, rect.width()*0.67, rect.height()*0.67);
24863 r.moveCenter(rect.center());
24864 painter->drawRect(r);
24885 qDebug() << Q_FUNC_INFO <<
"invalid key axis";
24900 double lowerPixelBound =
mKeyAxis.data()->coordToPixel(
mKeyAxis.data()->range().lower);
24901 double upperPixelBound =
mKeyAxis.data()->coordToPixel(
mKeyAxis.data()->range().upper);
24902 bool isVisible =
false;
24908 const QRectF barRect =
getBarRect(it->key, it->value);
24909 if (
mKeyAxis.data()->orientation() == Qt::Horizontal)
24910 isVisible = ((!
mKeyAxis.data()->rangeReversed() && barRect.right() >= lowerPixelBound) || (
mKeyAxis.data()->rangeReversed() && barRect.left() <= lowerPixelBound));
24912 isVisible = ((!
mKeyAxis.data()->rangeReversed() && barRect.top() <= lowerPixelBound) || (
mKeyAxis.data()->rangeReversed() && barRect.bottom() >= lowerPixelBound));
24922 const QRectF barRect =
getBarRect(it->key, it->value);
24923 if (
mKeyAxis.data()->orientation() == Qt::Horizontal)
24924 isVisible = ((!
mKeyAxis.data()->rangeReversed() && barRect.left() <= upperPixelBound) || (
mKeyAxis.data()->rangeReversed() && barRect.right() >= upperPixelBound));
24926 isVisible = ((!
mKeyAxis.data()->rangeReversed() && barRect.bottom() >= upperPixelBound) || (
mKeyAxis.data()->rangeReversed() && barRect.top() <= upperPixelBound));
24945 if (!
keyAxis || !
valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return {}; }
24947 double lowerPixelWidth, upperPixelWidth;
24955 double bottomOffset = (
mBarBelow &&
mPen != Qt::NoPen ? 1 : 0)*(
mPen.isCosmetic() ? 1 :
mPen.widthF());
24958 if (qAbs(valuePixel-basePixel) <= qAbs(bottomOffset))
24959 bottomOffset = valuePixel-basePixel;
24962 return QRectF(QPointF(keyPixel+lowerPixelWidth, valuePixel), QPointF(keyPixel+upperPixelWidth, basePixel+bottomOffset)).normalized();
24965 return QRectF(QPointF(basePixel+bottomOffset, keyPixel+lowerPixelWidth), QPointF(valuePixel, keyPixel+upperPixelWidth)).normalized();
24994 if (
mKeyAxis.data()->orientation() == Qt::Horizontal)
25000 qDebug() << Q_FUNC_INFO <<
"No key axis or axis rect defined";
25007 double keyPixel =
mKeyAxis.data()->coordToPixel(key);
25013 qDebug() << Q_FUNC_INFO <<
"No key axis defined";
25034 double epsilon = qAbs(key)*(
sizeof(key)==4 ? 1e-6 : 1e-14);
25036 epsilon = (
sizeof(key)==4 ? 1e-6 : 1e-14);
25039 while (it != itEnd)
25041 if (it->key > key-epsilon && it->key < key+epsilon)
25043 if ((positive && it->value > max) ||
25044 (!positive && it->value < max))
25050 return max +
mBarBelow.data()->getStackedBaseValue(key, positive);
25065 if (!lower && !upper)
return;
25071 upper->
mBarBelow.data()->mBarAbove =
nullptr;
25077 lower->
mBarAbove.data()->mBarBelow =
nullptr;
25083 lower->
mBarAbove.data()->mBarBelow =
nullptr;
25086 upper->
mBarBelow.data()->mBarAbove =
nullptr;
25210 lowerQuartile(lowerQuartile),
25212 upperQuartile(upperQuartile),
25295 mWhiskerWidth(0.2),
25296 mWhiskerPen(Qt::black, 0, Qt::DashLine, Qt::FlatCap),
25297 mWhiskerBarPen(Qt::black),
25298 mWhiskerAntialiased(false),
25299 mMedianPen(Qt::black, 3, Qt::SolidLine, Qt::FlatCap),
25302 setPen(QPen(Qt::black));
25337 void QCPStatisticalBox::setData(
const QVector<double> &keys,
const QVector<double> &minimum,
const QVector<double> &lowerQuartile,
const QVector<double> &median,
const QVector<double> &upperQuartile,
const QVector<double> &maximum,
bool alreadySorted)
25340 addData(keys, minimum, lowerQuartile, median, upperQuartile, maximum, alreadySorted);
25438 void QCPStatisticalBox::addData(
const QVector<double> &keys,
const QVector<double> &minimum,
const QVector<double> &lowerQuartile,
const QVector<double> &median,
const QVector<double> &upperQuartile,
const QVector<double> &maximum,
bool alreadySorted)
25440 if (keys.size() != minimum.size() || minimum.size() != lowerQuartile.size() || lowerQuartile.size() != median.size() ||
25441 median.size() != upperQuartile.size() || upperQuartile.size() != maximum.size() || maximum.size() != keys.size())
25442 qDebug() << Q_FUNC_INFO <<
"keys, minimum, lowerQuartile, median, upperQuartile, maximum have different sizes:"
25443 << keys.size() << minimum.size() << lowerQuartile.size() << median.size() << upperQuartile.size() << maximum.size();
25444 const int n = qMin(keys.size(), qMin(minimum.size(), qMin(lowerQuartile.size(), qMin(median.size(), qMin(upperQuartile.size(), maximum.size())))));
25445 QVector<QCPStatisticalBoxData> tempData(n);
25446 QVector<QCPStatisticalBoxData>::iterator it = tempData.begin();
25447 const QVector<QCPStatisticalBoxData>::iterator itEnd = tempData.end();
25449 while (it != itEnd)
25452 it->minimum = minimum[i];
25453 it->lowerQuartile = lowerQuartile[i];
25454 it->median = median[i];
25455 it->upperQuartile = upperQuartile[i];
25456 it->maximum = maximum[i];
25471 void QCPStatisticalBox::addData(
double key,
double minimum,
double lowerQuartile,
double median,
double upperQuartile,
double maximum,
const QVector<double> &outliers)
25521 double minDistSqr = (std::numeric_limits<double>::max)();
25527 if (currentDistSqr < minDistSqr)
25529 minDistSqr = currentDistSqr;
25530 closestDataPoint = it;
25536 foreach (
const QLineF &backbone, whiskerBackbones)
25539 if (currentDistSqr < minDistSqr)
25541 minDistSqr = currentDistSqr;
25542 closestDataPoint = it;
25549 int pointIndex = int(closestDataPoint-
mDataContainer->constBegin());
25552 return qSqrt(minDistSqr);
25575 return mDataContainer->valueRange(foundRange, inSignDomain, inKeyRange);
25584 if (!
keyAxis || !
valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return; }
25590 QList<QCPDataRange> selectedSegments, unselectedSegments, allSegments;
25592 allSegments << unselectedSegments << selectedSegments;
25593 for (
int i=0; i<allSegments.size(); ++i)
25595 bool isSelectedSegment = i >= unselectedSegments.size();
25598 mDataContainer->limitIteratorsToDataRange(begin, end, allSegments.at(i));
25605 # ifdef QCUSTOMPLOT_CHECK_DATA
25609 qDebug() << Q_FUNC_INFO <<
"Data point at" << it->key <<
"of drawn range has invalid data." <<
"Plottable name:" <<
name();
25610 for (
int i=0; i<it->outliers.size(); ++i)
25612 qDebug() << Q_FUNC_INFO <<
"Data point outlier at" << it->key <<
"of drawn range invalid." <<
"Plottable name:" <<
name();
25622 painter->setBrush(
mBrush);
25642 painter->setBrush(
mBrush);
25643 QRectF r = QRectF(0, 0, rect.width()*0.67, rect.height()*0.67);
25644 r.moveCenter(rect.center());
25645 painter->drawRect(r);
25661 painter->drawRect(quartileBox);
25664 painter->setClipRect(quartileBox, Qt::IntersectClip);
25677 for (
int i=0; i<it->outliers.size(); ++i)
25699 qDebug() << Q_FUNC_INFO <<
"invalid key axis";
25733 QVector<QLineF> result(2);
25748 QVector<QLineF> result(2);
25816 mKeyRange(keyRange),
25817 mValueRange(valueRange),
25821 mDataModified(true)
25842 mDataModified(true)
25853 if (&other !=
this)
25880 if (keyCell >= 0 && keyCell < mKeySize && valueCell >= 0 && valueCell <
mValueSize)
25889 if (keyIndex >= 0 && keyIndex < mKeySize && valueIndex >= 0 && valueIndex <
mValueSize)
25905 if (
mAlpha && keyIndex >= 0 && keyIndex < mKeySize && valueIndex >= 0 && valueIndex <
mValueSize)
25933 #ifdef __EXCEPTIONS
25937 #ifdef __EXCEPTIONS
25938 }
catch (...) {
mData =
nullptr; }
25943 qDebug() << Q_FUNC_INFO <<
"out of memory for data dimensions "<<
mKeySize <<
"*" <<
mValueSize;
26046 if (keyCell >= 0 && keyCell < mKeySize && valueCell >= 0 && valueCell <
mValueSize)
26070 if (keyIndex >= 0 && keyIndex < mKeySize && valueIndex >= 0 && valueIndex <
mValueSize)
26079 qDebug() << Q_FUNC_INFO <<
"index out of bounds:" << keyIndex << valueIndex;
26099 if (keyIndex >= 0 && keyIndex < mKeySize && valueIndex >= 0 && valueIndex <
mValueSize)
26107 qDebug() << Q_FUNC_INFO <<
"index out of bounds:" << keyIndex << valueIndex;
26127 double minHeight =
mData[0];
26128 double maxHeight =
mData[0];
26130 for (
int i=0; i<dataCount; ++i)
26132 if (
mData[i] > maxHeight)
26133 maxHeight =
mData[i];
26134 if (
mData[i] < minHeight)
26135 minHeight =
mData[i];
26171 for (
int i=0; i<dataCount; ++i)
26191 for (
int i=0; i<dataCount; ++i)
26264 #ifdef __EXCEPTIONS
26268 #ifdef __EXCEPTIONS
26269 }
catch (...) {
mAlpha =
nullptr; }
26273 if (initializeOpaque)
26278 qDebug() << Q_FUNC_INFO <<
"out of memory for data dimensions "<<
mKeySize <<
"*" <<
mValueSize;
26410 mDataScaleType(
QCPAxis::stLinear),
26413 mInterpolate(true),
26414 mTightBoundary(false),
26415 mMapImageInvalidated(true)
26435 qDebug() << Q_FUNC_INFO <<
"The data pointer is already in (and owned by) this plottable" <<
reinterpret_cast<quintptr
>(
data);
26599 if (recalculateDataBounds)
26627 mLegendIcon = QPixmap::fromImage(
mMapImage.mirrored(mirrorX, mirrorY)).scaled(thumbSize, Qt::KeepAspectRatio, transformMode);
26642 double posKey, posValue;
26664 else if (result.
lower <= 0 && result.
upper <= 0)
26665 foundRange =
false;
26670 else if (result.
upper >= 0 && result.
lower >= 0)
26671 foundRange =
false;
26683 foundRange =
false;
26695 else if (result.
lower <= 0 && result.
upper <= 0)
26696 foundRange =
false;
26701 else if (result.
upper >= 0 && result.
lower >= 0)
26702 foundRange =
false;
26727 const QImage::Format format = QImage::Format_ARGB32_Premultiplied;
26730 int keyOversamplingFactor =
mInterpolate ? 1 : int(1.0+100.0/
double(keySize));
26731 int valueOversamplingFactor =
mInterpolate ? 1 : int(1.0+100.0/
double(valueSize));
26735 mMapImage = QImage(QSize(keySize*keyOversamplingFactor, valueSize*valueOversamplingFactor), format);
26737 mMapImage = QImage(QSize(valueSize*valueOversamplingFactor, keySize*keyOversamplingFactor), format);
26741 qDebug() << Q_FUNC_INFO <<
"Couldn't create map image (possibly too large for memory)";
26742 mMapImage = QImage(QSize(10, 10), format);
26747 if (keyOversamplingFactor > 1 || valueOversamplingFactor > 1)
26762 const int lineCount = valueSize;
26763 const int rowCount = keySize;
26764 for (
int line=0; line<lineCount; ++line)
26766 QRgb* pixels =
reinterpret_cast<QRgb*
>(localMapImage->scanLine(lineCount-1-line));
26774 const int lineCount = keySize;
26775 const int rowCount = valueSize;
26776 for (
int line=0; line<lineCount; ++line)
26778 QRgb* pixels =
reinterpret_cast<QRgb*
>(localMapImage->scanLine(lineCount-1-line));
26786 if (keyOversamplingFactor > 1 || valueOversamplingFactor > 1)
26789 mMapImage =
mUndersampledMapImage.scaled(keySize*keyOversamplingFactor, valueSize*valueOversamplingFactor, Qt::IgnoreAspectRatio, Qt::FastTransformation);
26791 mMapImage =
mUndersampledMapImage.scaled(valueSize*valueOversamplingFactor, keySize*keyOversamplingFactor, Qt::IgnoreAspectRatio, Qt::FastTransformation);
26811 QRectF mapBufferTarget;
26815 const double mapBufferPixelRatio = 3;
26816 mapBufferTarget = painter->clipRegion().boundingRect();
26817 mapBuffer = QPixmap((mapBufferTarget.size()*mapBufferPixelRatio).toSize());
26818 mapBuffer.fill(Qt::transparent);
26820 localPainter->scale(mapBufferPixelRatio, mapBufferPixelRatio);
26821 localPainter->translate(-mapBufferTarget.topLeft());
26827 double halfCellWidth = 0;
26828 double halfCellHeight = 0;
26829 if (
keyAxis()->orientation() == Qt::Horizontal)
26838 halfCellHeight = 0.5*imageRect.height()/double(
mMapData->
keySize()-1);
26842 imageRect.adjust(-halfCellWidth, -halfCellHeight, halfCellWidth, halfCellHeight);
26845 const bool smoothBackup = localPainter->renderHints().testFlag(QPainter::SmoothPixmapTransform);
26846 localPainter->setRenderHint(QPainter::SmoothPixmapTransform,
mInterpolate);
26847 QRegion clipBackup;
26850 clipBackup = localPainter->clipRegion();
26853 localPainter->setClipRect(tightClipRect, Qt::IntersectClip);
26855 localPainter->drawImage(imageRect,
mMapImage.mirrored(mirrorX, mirrorY));
26857 localPainter->setClipRegion(clipBackup);
26858 localPainter->setRenderHint(QPainter::SmoothPixmapTransform, smoothBackup);
26862 delete localPainter;
26863 painter->drawPixmap(mapBufferTarget.toRect(), mapBuffer);
26874 QPixmap scaledIcon =
mLegendIcon.scaled(rect.size().toSize(), Qt::KeepAspectRatio, Qt::FastTransformation);
26875 QRectF iconRect = QRectF(0, 0, scaledIcon.width(), scaledIcon.height());
26876 iconRect.moveCenter(rect.center());
26877 painter->drawPixmap(iconRect.topLeft(), scaledIcon);
27067 mChartStyle(csCandlestick),
27069 mWidthType(wtPlotCoords),
27071 mBrushPositive(QBrush(QColor(50, 160, 0))),
27072 mBrushNegative(QBrush(QColor(180, 0, 15))),
27073 mPenPositive(QPen(QColor(40, 150, 0))),
27074 mPenNegative(QPen(QColor(170, 5, 5)))
27114 void QCPFinancial::setData(
const QVector<double> &keys,
const QVector<double> &open,
const QVector<double> &high,
const QVector<double> &low,
const QVector<double> &close,
bool alreadySorted)
27117 addData(keys, open, high, low, close, alreadySorted);
27235 void QCPFinancial::addData(
const QVector<double> &keys,
const QVector<double> &open,
const QVector<double> &high,
const QVector<double> &low,
const QVector<double> &close,
bool alreadySorted)
27237 if (keys.size() != open.size() || open.size() != high.size() || high.size() != low.size() || low.size() != close.size() || close.size() != keys.size())
27238 qDebug() << Q_FUNC_INFO <<
"keys, open, high, low, close have different sizes:" << keys.size() << open.size() << high.size() << low.size() << close.size();
27239 const int n = qMin(keys.size(), qMin(open.size(), qMin(high.size(), qMin(low.size(), close.size()))));
27240 QVector<QCPFinancialData> tempData(n);
27241 QVector<QCPFinancialData>::iterator it = tempData.begin();
27242 const QVector<QCPFinancialData>::iterator itEnd = tempData.end();
27244 while (it != itEnd)
27247 it->open = open[i];
27248 it->high = high[i];
27250 it->close = close[i];
27318 double result = -1;
27322 result =
ohlcSelectTest(pos, visibleBegin, visibleEnd, closestDataPoint);
break;
27328 int pointIndex = int(closestDataPoint-
mDataContainer->constBegin());
27355 return mDataContainer->valueRange(foundRange, inSignDomain, inKeyRange);
27375 int count = qMin(time.size(), value.size());
27379 QCPFinancialData currentBinData(0, value.first(), value.first(), value.first(), value.first());
27380 int currentBinIndex = qFloor((time.first()-timeBinOffset)/timeBinSize+0.5);
27381 for (
int i=0; i<count; ++i)
27383 int index = qFloor((time.at(i)-timeBinOffset)/timeBinSize+0.5);
27384 if (currentBinIndex == index)
27386 if (value.at(i) < currentBinData.
low) currentBinData.
low = value.at(i);
27387 if (value.at(i) > currentBinData.
high) currentBinData.
high = value.at(i);
27390 currentBinData.
close = value.at(i);
27391 currentBinData.
key = timeBinOffset+(index)*timeBinSize;
27392 data.add(currentBinData);
27397 currentBinData.
close = value.at(i-1);
27398 currentBinData.
key = timeBinOffset+(index-1)*timeBinSize;
27399 data.add(currentBinData);
27401 currentBinIndex = index;
27402 currentBinData.
open = value.at(i);
27403 currentBinData.
high = value.at(i);
27404 currentBinData.
low = value.at(i);
27419 QList<QCPDataRange> selectedSegments, unselectedSegments, allSegments;
27421 allSegments << unselectedSegments << selectedSegments;
27422 for (
int i=0; i<allSegments.size(); ++i)
27424 bool isSelectedSegment = i >= unselectedSegments.size();
27427 mDataContainer->limitIteratorsToDataRange(begin, end, allSegments.at(i));
27435 drawOhlcPlot(painter, begin, end, isSelectedSegment);
break;
27457 painter->setClipRegion(QRegion(QPolygon() << rect.bottomLeft().toPoint() << rect.topRight().toPoint() << rect.topLeft().toPoint()));
27458 painter->
drawLine(QLineF(0, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft()));
27459 painter->
drawLine(QLineF(rect.width()*0.2, rect.height()*0.3, rect.width()*0.2, rect.height()*0.5).translated(rect.topLeft()));
27460 painter->
drawLine(QLineF(rect.width()*0.8, rect.height()*0.5, rect.width()*0.8, rect.height()*0.7).translated(rect.topLeft()));
27464 painter->setClipRegion(QRegion(QPolygon() << rect.bottomLeft().toPoint() << rect.topRight().toPoint() << rect.bottomRight().toPoint()));
27465 painter->
drawLine(QLineF(0, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft()));
27466 painter->
drawLine(QLineF(rect.width()*0.2, rect.height()*0.3, rect.width()*0.2, rect.height()*0.5).translated(rect.topLeft()));
27467 painter->
drawLine(QLineF(rect.width()*0.8, rect.height()*0.5, rect.width()*0.8, rect.height()*0.7).translated(rect.topLeft()));
27470 painter->setBrush(
mBrush);
27472 painter->
drawLine(QLineF(0, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft()));
27473 painter->
drawLine(QLineF(rect.width()*0.2, rect.height()*0.3, rect.width()*0.2, rect.height()*0.5).translated(rect.topLeft()));
27474 painter->
drawLine(QLineF(rect.width()*0.8, rect.height()*0.5, rect.width()*0.8, rect.height()*0.7).translated(rect.topLeft()));
27483 painter->setClipRegion(QRegion(QPolygon() << rect.bottomLeft().toPoint() << rect.topRight().toPoint() << rect.topLeft().toPoint()));
27484 painter->
drawLine(QLineF(0, rect.height()*0.5, rect.width()*0.25, rect.height()*0.5).translated(rect.topLeft()));
27485 painter->
drawLine(QLineF(rect.width()*0.75, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft()));
27486 painter->drawRect(QRectF(rect.width()*0.25, rect.height()*0.25, rect.width()*0.5, rect.height()*0.5).translated(rect.topLeft()));
27490 painter->setClipRegion(QRegion(QPolygon() << rect.bottomLeft().toPoint() << rect.topRight().toPoint() << rect.bottomRight().toPoint()));
27491 painter->
drawLine(QLineF(0, rect.height()*0.5, rect.width()*0.25, rect.height()*0.5).translated(rect.topLeft()));
27492 painter->
drawLine(QLineF(rect.width()*0.75, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft()));
27493 painter->drawRect(QRectF(rect.width()*0.25, rect.height()*0.25, rect.width()*0.5, rect.height()*0.5).translated(rect.topLeft()));
27496 painter->setBrush(
mBrush);
27498 painter->
drawLine(QLineF(0, rect.height()*0.5, rect.width()*0.25, rect.height()*0.5).translated(rect.topLeft()));
27499 painter->
drawLine(QLineF(rect.width()*0.75, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft()));
27500 painter->drawRect(QRectF(rect.width()*0.25, rect.height()*0.25, rect.width()*0.5, rect.height()*0.5).translated(rect.topLeft()));
27515 if (!
keyAxis || !
valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return; }
27534 painter->
drawLine(QPointF(keyPixel-pixelWidth, openPixel), QPointF(keyPixel, openPixel));
27536 painter->
drawLine(QPointF(keyPixel, closePixel), QPointF(keyPixel+pixelWidth, closePixel));
27555 painter->
drawLine(QPointF(openPixel, keyPixel-pixelWidth), QPointF(openPixel, keyPixel));
27557 painter->
drawLine(QPointF(closePixel, keyPixel), QPointF(closePixel, keyPixel+pixelWidth));
27572 if (!
keyAxis || !
valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return; }
27589 painter->setBrush(
mBrush);
27600 painter->drawRect(QRectF(QPointF(keyPixel-pixelWidth, closePixel), QPointF(keyPixel+pixelWidth, openPixel)));
27617 painter->setBrush(
mBrush);
27628 painter->drawRect(QRectF(QPointF(closePixel, keyPixel-pixelWidth), QPointF(openPixel, keyPixel+pixelWidth)));
27660 if (
mKeyAxis.data()->orientation() == Qt::Horizontal)
27665 qDebug() << Q_FUNC_INFO <<
"No key axis or axis rect defined";
27671 result =
mKeyAxis.data()->coordToPixel(key+
mWidth*0.5)-keyPixel;
27673 qDebug() << Q_FUNC_INFO <<
"No key axis defined";
27693 if (!
keyAxis || !
valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return -1; }
27695 double minDistSqr = (std::numeric_limits<double>::max)();
27703 if (currentDistSqr < minDistSqr)
27705 minDistSqr = currentDistSqr;
27706 closestDataPoint = it;
27716 if (currentDistSqr < minDistSqr)
27718 minDistSqr = currentDistSqr;
27719 closestDataPoint = it;
27723 return qSqrt(minDistSqr);
27740 if (!
keyAxis || !
valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return -1; }
27742 double minDistSqr = (std::numeric_limits<double>::max)();
27747 double currentDistSqr;
27750 QCPRange boxValueRange(it->close, it->open);
27751 double posKey, posValue;
27762 currentDistSqr = qMin(highLineDistSqr, lowLineDistSqr);
27764 if (currentDistSqr < minDistSqr)
27766 minDistSqr = currentDistSqr;
27767 closestDataPoint = it;
27774 double currentDistSqr;
27777 QCPRange boxValueRange(it->close, it->open);
27778 double posKey, posValue;
27789 currentDistSqr = qMin(highLineDistSqr, lowLineDistSqr);
27791 if (currentDistSqr < minDistSqr)
27793 minDistSqr = currentDistSqr;
27794 closestDataPoint = it;
27798 return qSqrt(minDistSqr);
27819 qDebug() << Q_FUNC_INFO <<
"invalid key axis";
27837 if (!
keyAxis || !
valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return {}; }
27844 return QRectF(keyPixel-keyWidthPixels, highPixel, keyWidthPixels*2, lowPixel-highPixel).normalized();
27846 return QRectF(highPixel, keyPixel-keyWidthPixels, lowPixel-highPixel, keyWidthPixels*2).normalized();
27896 errorMinus(errorMinus),
27897 errorPlus(errorPlus)
27962 mErrorType(etValueError),
27966 setPen(QPen(Qt::black, 0));
28025 addData(errorMinus, errorPlus);
28044 if (plottable && qobject_cast<QCPErrorBars*>(plottable))
28047 qDebug() << Q_FUNC_INFO <<
"can't set another QCPErrorBars instance as data plottable";
28053 qDebug() << Q_FUNC_INFO <<
"passed plottable doesn't implement 1d interface, can't associate with QCPErrorBars";
28114 if (errorMinus.size() != errorPlus.size())
28115 qDebug() << Q_FUNC_INFO <<
"minus and plus error vectors have different sizes:" << errorMinus.size() << errorPlus.size();
28116 const int n = qMin(errorMinus.size(), errorPlus.size());
28118 for (
int i=0; i<n; ++i)
28163 qDebug() << Q_FUNC_INFO <<
"no data plottable set";
28173 qDebug() << Q_FUNC_INFO <<
"no data plottable set";
28183 qDebug() << Q_FUNC_INFO <<
"no data plottable set";
28192 const double value =
mDataPlottable->interface1D()->dataMainValue(index);
28196 return {value, value};
28199 qDebug() << Q_FUNC_INFO <<
"no data plottable set";
28210 qDebug() << Q_FUNC_INFO <<
"no data plottable set";
28222 qDebug() << Q_FUNC_INFO <<
"no data plottable set";
28240 QCPErrorBarsDataContainer::const_iterator visibleBegin, visibleEnd;
28243 QVector<QLineF> backbones, whiskers;
28244 for (QCPErrorBarsDataContainer::const_iterator it=visibleBegin; it!=visibleEnd; ++it)
28249 foreach (
const QLineF &backbone, backbones)
28269 int beginIndex =
mDataPlottable->interface1D()->findBegin(sortKey, expandedRange);
28274 qDebug() << Q_FUNC_INFO <<
"no data plottable set";
28285 int endIndex =
mDataPlottable->interface1D()->findEnd(sortKey, expandedRange);
28290 qDebug() << Q_FUNC_INFO <<
"no data plottable set";
28313 QCPErrorBarsDataContainer::const_iterator closestDataPoint =
mDataContainer->constEnd();
28317 int pointIndex = int(closestDataPoint-
mDataContainer->constBegin());
28329 if (!
mKeyAxis || !
mValueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return; }
28334 bool checkPointVisibility = !
mDataPlottable->interface1D()->sortKeyIsMainKey();
28337 #ifdef QCUSTOMPLOT_CHECK_DATA
28338 QCPErrorBarsDataContainer::const_iterator it;
28342 qDebug() << Q_FUNC_INFO <<
"Data point at index" << it-
mDataContainer->constBegin() <<
"invalid." <<
"Plottable name:" <<
name();
28347 painter->setBrush(Qt::NoBrush);
28349 QList<QCPDataRange> selectedSegments, unselectedSegments, allSegments;
28351 allSegments << unselectedSegments << selectedSegments;
28352 QVector<QLineF> backbones, whiskers;
28353 for (
int i=0; i<allSegments.size(); ++i)
28355 QCPErrorBarsDataContainer::const_iterator begin, end;
28360 bool isSelectedSegment = i >= unselectedSegments.size();
28365 if (painter->pen().capStyle() == Qt::SquareCap)
28367 QPen capFixPen(painter->pen());
28368 capFixPen.setCapStyle(Qt::FlatCap);
28369 painter->
setPen(capFixPen);
28373 for (QCPErrorBarsDataContainer::const_iterator it=begin; it!=end; ++it)
28378 painter->drawLines(backbones);
28379 painter->drawLines(whiskers);
28394 painter->
drawLine(QLineF(rect.center().x(), rect.top()+2, rect.center().x(), rect.bottom()-1));
28395 painter->
drawLine(QLineF(rect.center().x()-4, rect.top()+2, rect.center().x()+4, rect.top()+2));
28396 painter->
drawLine(QLineF(rect.center().x()-4, rect.bottom()-1, rect.center().x()+4, rect.bottom()-1));
28399 painter->
drawLine(QLineF(rect.left()+2, rect.center().y(), rect.right()-2, rect.center().y()));
28400 painter->
drawLine(QLineF(rect.left()+2, rect.center().y()-4, rect.left()+2, rect.center().y()+4));
28401 painter->
drawLine(QLineF(rect.right()-2, rect.center().y()-4, rect.right()-2, rect.center().y()+4));
28410 foundRange =
false;
28415 bool haveLower =
false;
28416 bool haveUpper =
false;
28417 QCPErrorBarsDataContainer::const_iterator it;
28424 if (qIsNaN(current))
continue;
28427 if (current < range.
lower || !haveLower)
28429 range.
lower = current;
28432 if (current > range.
upper || !haveUpper)
28434 range.
upper = current;
28441 if (qIsNaN(dataKey))
continue;
28443 double current = dataKey + (qIsNaN(it->errorPlus) ? 0 : it->errorPlus);
28446 if (current > range.
upper || !haveUpper)
28448 range.
upper = current;
28453 current = dataKey - (qIsNaN(it->errorMinus) ? 0 : it->errorMinus);
28456 if (current < range.
lower || !haveLower)
28458 range.
lower = current;
28465 if (haveUpper && !haveLower)
28469 }
else if (haveLower && !haveUpper)
28475 foundRange = haveLower && haveUpper;
28484 foundRange =
false;
28489 const bool restrictKeyRange = inKeyRange !=
QCPRange();
28490 bool haveLower =
false;
28491 bool haveUpper =
false;
28492 QCPErrorBarsDataContainer::const_iterator itBegin =
mDataContainer->constBegin();
28493 QCPErrorBarsDataContainer::const_iterator itEnd =
mDataContainer->constEnd();
28494 if (
mDataPlottable->interface1D()->sortKeyIsMainKey() && restrictKeyRange)
28499 for (QCPErrorBarsDataContainer::const_iterator it = itBegin; it != itEnd; ++it)
28501 if (restrictKeyRange)
28504 if (dataKey < inKeyRange.lower || dataKey > inKeyRange.
upper)
28510 if (qIsNaN(dataValue))
continue;
28512 double current = dataValue + (qIsNaN(it->errorPlus) ? 0 : it->errorPlus);
28515 if (current > range.
upper || !haveUpper)
28517 range.
upper = current;
28522 current = dataValue - (qIsNaN(it->errorMinus) ? 0 : it->errorMinus);
28525 if (current < range.
lower || !haveLower)
28527 range.
lower = current;
28535 if (qIsNaN(current))
continue;
28538 if (current < range.
lower || !haveLower)
28540 range.
lower = current;
28543 if (current > range.
upper || !haveUpper)
28545 range.
upper = current;
28552 if (haveUpper && !haveLower)
28556 }
else if (haveLower && !haveUpper)
28562 foundRange = haveLower && haveUpper;
28582 QPointF centerPixel =
mDataPlottable->interface1D()->dataPixelPosition(index);
28583 if (qIsNaN(centerPixel.x()) || qIsNaN(centerPixel.y()))
28587 const double centerErrorAxisPixel = errorAxis->
orientation() == Qt::Horizontal ? centerPixel.x() : centerPixel.y();
28588 const double centerOrthoAxisPixel = orthoAxis->
orientation() == Qt::Horizontal ? centerPixel.x() : centerPixel.y();
28589 const double centerErrorAxisCoord = errorAxis->
pixelToCoord(centerErrorAxisPixel);
28592 double errorStart, errorEnd;
28593 if (!qIsNaN(it->errorPlus))
28595 errorStart = centerErrorAxisPixel+
symbolGap;
28596 errorEnd = errorAxis->
coordToPixel(centerErrorAxisCoord+it->errorPlus);
28600 backbones.append(QLineF(centerOrthoAxisPixel, errorStart, centerOrthoAxisPixel, errorEnd));
28601 whiskers.append(QLineF(centerOrthoAxisPixel-
mWhiskerWidth*0.5, errorEnd, centerOrthoAxisPixel+
mWhiskerWidth*0.5, errorEnd));
28605 backbones.append(QLineF(errorStart, centerOrthoAxisPixel, errorEnd, centerOrthoAxisPixel));
28606 whiskers.append(QLineF(errorEnd, centerOrthoAxisPixel-
mWhiskerWidth*0.5, errorEnd, centerOrthoAxisPixel+
mWhiskerWidth*0.5));
28610 if (!qIsNaN(it->errorMinus))
28612 errorStart = centerErrorAxisPixel-
symbolGap;
28613 errorEnd = errorAxis->
coordToPixel(centerErrorAxisCoord-it->errorMinus);
28617 backbones.append(QLineF(centerOrthoAxisPixel, errorStart, centerOrthoAxisPixel, errorEnd));
28618 whiskers.append(QLineF(centerOrthoAxisPixel-
mWhiskerWidth*0.5, errorEnd, centerOrthoAxisPixel+
mWhiskerWidth*0.5, errorEnd));
28622 backbones.append(QLineF(errorStart, centerOrthoAxisPixel, errorEnd, centerOrthoAxisPixel));
28623 whiskers.append(QLineF(errorEnd, centerOrthoAxisPixel-
mWhiskerWidth*0.5, errorEnd, centerOrthoAxisPixel+
mWhiskerWidth*0.5));
28652 qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
28669 dataRange = dataRange.
bounded(rangeRestriction);
28679 int i = beginIndex;
28680 while (i > 0 && i < n && i > rangeRestriction.
begin())
28687 while (i >= 0 && i < n && i < rangeRestriction.
end())
28712 qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
28716 QCPErrorBarsDataContainer::const_iterator begin, end;
28720 double minDistSqr = (std::numeric_limits<double>::max)();
28721 QVector<QLineF> backbones, whiskers;
28722 for (QCPErrorBarsDataContainer::const_iterator it=begin; it!=end; ++it)
28725 foreach (
const QLineF &backbone, backbones)
28728 if (currentDistSqr < minDistSqr)
28730 minDistSqr = currentDistSqr;
28735 return qSqrt(minDistSqr);
28747 selectedSegments.clear();
28748 unselectedSegments.clear();
28775 QPointF centerPixel =
mDataPlottable->interface1D()->dataPixelPosition(index);
28776 const double centerKeyPixel =
mKeyAxis->orientation() == Qt::Horizontal ? centerPixel.x() : centerPixel.y();
28777 if (qIsNaN(centerKeyPixel))
28780 double keyMin, keyMax;
28783 const double centerKey =
mKeyAxis->pixelToCoord(centerKeyPixel);
28786 keyMax = centerKey+(qIsNaN(errorPlus) ? 0 : errorPlus);
28787 keyMin = centerKey-(qIsNaN(errorMinus) ? 0 : errorMinus);
28793 return ((keyMax >
mKeyAxis->range().lower) && (keyMin <
mKeyAxis->range().upper));
28805 if (pixelRect.left() > line.x1() && pixelRect.left() > line.x2())
28807 else if (pixelRect.right() < line.x1() && pixelRect.right() < line.x2())
28809 else if (pixelRect.top() > line.y1() && pixelRect.top() > line.y2())
28811 else if (pixelRect.bottom() < line.y1() && pixelRect.bottom() < line.y2())
28842 point1(createPosition(QLatin1String(
"point1"))),
28843 point2(createPosition(QLatin1String(
"point2")))
28848 setPen(QPen(Qt::black));
28892 int clipPad = qCeil(
mainPen().widthF());
28895 if (!line.isNull())
28914 if (vec.
x() == 0 && vec.
y() == 0)
28916 if (qFuzzyIsNull(vec.
x()))
28921 gamma = base.
x()-bx + (by-base.
y())*vec.
x()/vec.
y();
28922 if (gamma >= 0 && gamma <= rect.width())
28923 result.setLine(bx+gamma, rect.top(), bx+gamma, rect.bottom());
28924 }
else if (qFuzzyIsNull(vec.
y()))
28929 gamma = base.
y()-by + (bx-base.
x())*vec.
y()/vec.
x();
28930 if (gamma >= 0 && gamma <= rect.height())
28931 result.setLine(rect.left(), by+gamma, rect.right(), by+gamma);
28934 QList<QCPVector2D> pointVectors;
28938 gamma = base.
x()-bx + (by-base.
y())*vec.
x()/vec.
y();
28939 if (gamma >= 0 && gamma <= rect.width())
28943 by = rect.bottom();
28944 gamma = base.
x()-bx + (by-base.
y())*vec.
x()/vec.
y();
28945 if (gamma >= 0 && gamma <= rect.width())
28950 gamma = base.
y()-by + (bx-base.
x())*vec.
y()/vec.
x();
28951 if (gamma >= 0 && gamma <= rect.height())
28956 gamma = base.
y()-by + (bx-base.
x())*vec.
y()/vec.
x();
28957 if (gamma >= 0 && gamma <= rect.height())
28961 if (pointVectors.size() == 2)
28963 result.setPoints(pointVectors.at(0).toPointF(), pointVectors.at(1).toPointF());
28964 }
else if (pointVectors.size() > 2)
28967 double distSqrMax = 0;
28969 for (
int i=0; i<pointVectors.size()-1; ++i)
28971 for (
int k=i+1; k<pointVectors.size(); ++k)
28973 double distSqr = (pointVectors.at(i)-pointVectors.at(k)).lengthSquared();
28974 if (distSqr > distSqrMax)
28976 pv1 = pointVectors.at(i);
28977 pv2 = pointVectors.at(k);
28978 distSqrMax = distSqr;
29025 start(createPosition(QLatin1String(
"start"))),
29026 end(createPosition(QLatin1String(
"end")))
29031 setPen(QPen(Qt::black));
29100 if (qFuzzyIsNull((startVec-endVec).lengthSquared()))
29104 clipPad = qMax(clipPad, qCeil(
mainPen().widthF()));
29107 if (!line.isNull())
29111 painter->setBrush(Qt::SolidPattern);
29113 mTail.
draw(painter, startVec, startVec-endVec);
29115 mHead.
draw(painter, endVec, endVec-startVec);
29128 bool containsStart = rect.contains(qRound(
start.x()), qRound(
start.y()));
29129 bool containsEnd = rect.contains(qRound(
end.x()), qRound(
end.y()));
29130 if (containsStart && containsEnd)
29131 return {
start.toPointF(),
end.toPointF()};
29138 QList<QCPVector2D> pointVectors;
29140 if (!qFuzzyIsNull(vec.
y()))
29145 mu = (by-base.
y())/vec.
y();
29146 if (mu >= 0 && mu <= 1)
29148 gamma = base.
x()-bx + mu*vec.
x();
29149 if (gamma >= 0 && gamma <= rect.width())
29154 by = rect.bottom();
29155 mu = (by-base.
y())/vec.
y();
29156 if (mu >= 0 && mu <= 1)
29158 gamma = base.
x()-bx + mu*vec.
x();
29159 if (gamma >= 0 && gamma <= rect.width())
29163 if (!qFuzzyIsNull(vec.
x()))
29168 mu = (bx-base.
x())/vec.
x();
29169 if (mu >= 0 && mu <= 1)
29171 gamma = base.
y()-by + mu*vec.
y();
29172 if (gamma >= 0 && gamma <= rect.height())
29178 mu = (bx-base.
x())/vec.
x();
29179 if (mu >= 0 && mu <= 1)
29181 gamma = base.
y()-by + mu*vec.
y();
29182 if (gamma >= 0 && gamma <= rect.height())
29188 pointVectors.append(
start);
29190 pointVectors.append(
end);
29193 if (pointVectors.size() == 2)
29195 result.setPoints(pointVectors.at(0).toPointF(), pointVectors.at(1).toPointF());
29196 }
else if (pointVectors.size() > 2)
29199 double distSqrMax = 0;
29201 for (
int i=0; i<pointVectors.size()-1; ++i)
29203 for (
int k=i+1; k<pointVectors.size(); ++k)
29205 double distSqr = (pointVectors.at(i)-pointVectors.at(k)).lengthSquared();
29206 if (distSqr > distSqrMax)
29208 pv1 = pointVectors.at(i);
29209 pv2 = pointVectors.at(k);
29210 distSqrMax = distSqr;
29263 start(createPosition(QLatin1String(
"start"))),
29264 startDir(createPosition(QLatin1String(
"startDir"))),
29265 endDir(createPosition(QLatin1String(
"endDir"))),
29266 end(createPosition(QLatin1String(
"end")))
29273 setPen(QPen(Qt::black));
29339 QPainterPath cubicPath(startVec);
29340 cubicPath.cubicTo(startDirVec, endDirVec, endVec);
29342 QList<QPolygonF> polygons = cubicPath.toSubpathPolygons();
29343 if (polygons.isEmpty())
29345 const QPolygonF polygon = polygons.first();
29347 double minDistSqr = (std::numeric_limits<double>::max)();
29348 for (
int i=1; i<polygon.size(); ++i)
29351 if (distSqr < minDistSqr)
29352 minDistSqr = distSqr;
29354 return qSqrt(minDistSqr);
29364 if ((endVec-startVec).length() > 1e10)
29367 QPainterPath cubicPath(startVec.
toPointF());
29371 const int clipEnlarge = qCeil(
mainPen().widthF());
29372 QRect clip =
clipRect().adjusted(-clipEnlarge, -clipEnlarge, clipEnlarge, clipEnlarge);
29373 QRect cubicRect = cubicPath.controlPointRect().toRect();
29374 if (cubicRect.isEmpty())
29375 cubicRect.adjust(0, 0, 1, 1);
29376 if (clip.intersects(cubicRect))
29379 painter->drawPath(cubicPath);
29380 painter->setBrush(Qt::SolidPattern);
29382 mTail.
draw(painter, startVec, M_PI-cubicPath.angleAtPercent(0)/180.0*M_PI);
29384 mHead.
draw(painter, endVec, -cubicPath.angleAtPercent(1)/180.0*M_PI);
29423 topLeft(createPosition(QLatin1String(
"topLeft"))),
29424 bottomRight(createPosition(QLatin1String(
"bottomRight"))),
29425 top(createAnchor(QLatin1String(
"top"), aiTop)),
29426 topRight(createAnchor(QLatin1String(
"topRight"), aiTopRight)),
29427 right(createAnchor(QLatin1String(
"right"), aiRight)),
29428 bottom(createAnchor(QLatin1String(
"bottom"), aiBottom)),
29429 bottomLeft(createAnchor(QLatin1String(
"bottomLeft"), aiBottomLeft)),
29430 left(createAnchor(QLatin1String(
"left"), aiLeft))
29435 setPen(QPen(Qt::black));
29495 bool filledRect =
mBrush.style() != Qt::NoBrush &&
mBrush.color().alpha() != 0;
29504 if (p1.toPoint() == p2.toPoint())
29506 QRectF rect = QRectF(p1, p2).normalized();
29507 double clipPad =
mainPen().widthF();
29508 QRectF boundingRect = rect.adjusted(-clipPad, -clipPad, clipPad, clipPad);
29509 if (boundingRect.intersects(
clipRect()))
29513 painter->drawRect(rect);
29523 case aiTop:
return (rect.topLeft()+rect.topRight())*0.5;
29525 case aiRight:
return (rect.topRight()+rect.bottomRight())*0.5;
29526 case aiBottom:
return (rect.bottomLeft()+rect.bottomRight())*0.5;
29528 case aiLeft:
return (rect.topLeft()+rect.bottomLeft())*0.5;
29531 qDebug() << Q_FUNC_INFO <<
"invalid anchorId" << anchorId;
29586 position(createPosition(QLatin1String(
"position"))),
29587 topLeft(createAnchor(QLatin1String(
"topLeft"), aiTopLeft)),
29588 top(createAnchor(QLatin1String(
"top"), aiTop)),
29589 topRight(createAnchor(QLatin1String(
"topRight"), aiTopRight)),
29590 right(createAnchor(QLatin1String(
"right"), aiRight)),
29591 bottomRight(createAnchor(QLatin1String(
"bottomRight"), aiBottomRight)),
29592 bottom(createAnchor(QLatin1String(
"bottom"), aiBottom)),
29593 bottomLeft(createAnchor(QLatin1String(
"bottomLeft"), aiBottomLeft)),
29594 left(createAnchor(QLatin1String(
"left"), aiLeft)),
29595 mText(QLatin1String(
"text")),
29596 mPositionAlignment(Qt::AlignCenter),
29597 mTextAlignment(Qt::AlignTop|Qt::AlignHCenter),
29758 QTransform inputTransform;
29759 inputTransform.translate(positionPixels.x(), positionPixels.y());
29761 inputTransform.translate(-positionPixels.x(), -positionPixels.y());
29762 QPointF rotatedPos = inputTransform.map(pos);
29763 QFontMetrics fontMetrics(
mFont);
29764 QRect textRect = fontMetrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip|
mTextAlignment,
mText);
29767 textBoxRect.moveTopLeft(textPos.toPoint());
29776 QTransform transform = painter->transform();
29777 transform.translate(pos.x(), pos.y());
29781 QRect textRect = painter->fontMetrics().boundingRect(0, 0, 0, 0, Qt::TextDontClip|
mTextAlignment,
mText);
29784 textRect.moveTopLeft(textPos.toPoint()+QPoint(
mPadding.left(),
mPadding.top()));
29785 textBoxRect.moveTopLeft(textPos.toPoint());
29786 int clipPad = qCeil(
mainPen().widthF());
29787 QRect boundingRect = textBoxRect.adjusted(-clipPad, -clipPad, clipPad, clipPad);
29788 if (transform.mapRect(boundingRect).intersects(painter->transform().mapRect(
clipRect())))
29790 painter->setTransform(transform);
29796 painter->drawRect(textBoxRect);
29798 painter->setBrush(Qt::NoBrush);
29809 QTransform transform;
29810 transform.translate(pos.x(), pos.y());
29813 QFontMetrics fontMetrics(
mainFont());
29814 QRect textRect = fontMetrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip|
mTextAlignment,
mText);
29817 textBoxRect.moveTopLeft(textPos.toPoint());
29818 QPolygonF rectPoly = transform.map(QPolygonF(textBoxRect));
29823 case aiTop:
return (rectPoly.at(0)+rectPoly.at(1))*0.5;
29825 case aiRight:
return (rectPoly.at(1)+rectPoly.at(2))*0.5;
29827 case aiBottom:
return (rectPoly.at(2)+rectPoly.at(3))*0.5;
29829 case aiLeft:
return (rectPoly.at(3)+rectPoly.at(0))*0.5;
29832 qDebug() << Q_FUNC_INFO <<
"invalid anchorId" << anchorId;
29851 QPointF result = pos;
29853 result.rx() -= rect.width()/2.0;
29855 result.rx() -= rect.width();
29857 result.ry() -= rect.height()/2.0;
29859 result.ry() -= rect.height();
29928 topLeft(createPosition(QLatin1String(
"topLeft"))),
29929 bottomRight(createPosition(QLatin1String(
"bottomRight"))),
29930 topLeftRim(createAnchor(QLatin1String(
"topLeftRim"), aiTopLeftRim)),
29931 top(createAnchor(QLatin1String(
"top"), aiTop)),
29932 topRightRim(createAnchor(QLatin1String(
"topRightRim"), aiTopRightRim)),
29933 right(createAnchor(QLatin1String(
"right"), aiRight)),
29934 bottomRightRim(createAnchor(QLatin1String(
"bottomRightRim"), aiBottomRightRim)),
29935 bottom(createAnchor(QLatin1String(
"bottom"), aiBottom)),
29936 bottomLeftRim(createAnchor(QLatin1String(
"bottomLeftRim"), aiBottomLeftRim)),
29937 left(createAnchor(QLatin1String(
"left"), aiLeft)),
29938 center(createAnchor(QLatin1String(
"center"), aiCenter))
29943 setPen(QPen(Qt::black));
30004 QPointF
center((p1+p2)/2.0);
30005 double a = qAbs(p1.x()-p2.x())/2.0;
30006 double b = qAbs(p1.y()-p2.y())/2.0;
30007 double x = pos.x()-
center.x();
30008 double y = pos.y()-
center.y();
30011 double c = 1.0/qSqrt(x*x/(a*a)+y*y/(b*b));
30012 double result = qAbs(c-1)*qSqrt(x*x+y*y);
30016 if (x*x/(a*a) + y*y/(b*b) <= 1)
30027 if (p1.toPoint() == p2.toPoint())
30029 QRectF ellipseRect = QRectF(p1, p2).normalized();
30030 const int clipEnlarge = qCeil(
mainPen().widthF());
30031 QRect clip =
clipRect().adjusted(-clipEnlarge, -clipEnlarge, clipEnlarge, clipEnlarge);
30032 if (ellipseRect.intersects(clip))
30036 #ifdef __EXCEPTIONS
30040 painter->drawEllipse(ellipseRect);
30041 #ifdef __EXCEPTIONS
30044 qDebug() << Q_FUNC_INFO <<
"Item too large for memory, setting invisible";
30057 case aiTopLeftRim:
return rect.center()+(rect.topLeft()-rect.center())*1/qSqrt(2);
30058 case aiTop:
return (rect.topLeft()+rect.topRight())*0.5;
30059 case aiTopRightRim:
return rect.center()+(rect.topRight()-rect.center())*1/qSqrt(2);
30060 case aiRight:
return (rect.topRight()+rect.bottomRight())*0.5;
30061 case aiBottomRightRim:
return rect.center()+(rect.bottomRight()-rect.center())*1/qSqrt(2);
30062 case aiBottom:
return (rect.bottomLeft()+rect.bottomRight())*0.5;
30063 case aiBottomLeftRim:
return rect.center()+(rect.bottomLeft()-rect.center())*1/qSqrt(2);
30064 case aiLeft:
return (rect.topLeft()+rect.bottomLeft())*0.5;
30065 case aiCenter:
return (rect.topLeft()+rect.bottomRight())*0.5;
30068 qDebug() << Q_FUNC_INFO <<
"invalid anchorId" << anchorId;
30123 topLeft(createPosition(QLatin1String(
"topLeft"))),
30124 bottomRight(createPosition(QLatin1String(
"bottomRight"))),
30125 top(createAnchor(QLatin1String(
"top"), aiTop)),
30126 topRight(createAnchor(QLatin1String(
"topRight"), aiTopRight)),
30127 right(createAnchor(QLatin1String(
"right"), aiRight)),
30128 bottom(createAnchor(QLatin1String(
"bottom"), aiBottom)),
30129 bottomLeft(createAnchor(QLatin1String(
"bottomLeft"), aiBottomLeft)),
30130 left(createAnchor(QLatin1String(
"left"), aiLeft)),
30132 mScaledPixmapInvalidated(true),
30133 mAspectRatioMode(Qt::KeepAspectRatio),
30134 mTransformationMode(Qt::SmoothTransformation)
30155 qDebug() << Q_FUNC_INFO <<
"pixmap is null";
30203 bool flipHorz =
false;
30204 bool flipVert =
false;
30206 int clipPad =
mainPen().style() == Qt::NoPen ? 0 : qCeil(
mainPen().widthF());
30207 QRect boundingRect = rect.adjusted(-clipPad, -clipPad, clipPad, clipPad);
30208 if (boundingRect.intersects(
clipRect()))
30213 if (
pen.style() != Qt::NoPen)
30216 painter->setBrush(Qt::NoBrush);
30217 painter->drawRect(rect);
30225 bool flipHorz =
false;
30226 bool flipVert =
false;
30231 rect.adjust(rect.width(), 0, -rect.width(), 0);
30233 rect.adjust(0, rect.height(), 0, -rect.height());
30237 case aiTop:
return (rect.topLeft()+rect.topRight())*0.5;
30239 case aiRight:
return (rect.topRight()+rect.bottomRight())*0.5;
30240 case aiBottom:
return (rect.bottomLeft()+rect.bottomRight())*0.5;
30242 case aiLeft:
return (rect.topLeft()+rect.bottomLeft())*0.5;
30245 qDebug() << Q_FUNC_INFO <<
"invalid anchorId" << anchorId;
30269 #ifdef QCP_DEVICEPIXELRATIO_SUPPORTED
30270 double devicePixelRatio =
mPixmap.devicePixelRatio();
30272 double devicePixelRatio = 1.0;
30274 if (finalRect.isNull())
30279 if (flipHorz || flipVert)
30281 #ifdef QCP_DEVICEPIXELRATIO_SUPPORTED
30307 bool flipHorz =
false;
30308 bool flipVert =
false;
30312 return {p1, QSize(0, 0)};
30315 QSize newSize = QSize(p2.x()-p1.x(), p2.y()-p1.y());
30317 if (newSize.width() < 0)
30320 newSize.rwidth() *= -1;
30323 if (newSize.height() < 0)
30326 newSize.rheight() *= -1;
30329 QSize scaledSize =
mPixmap.size();
30330 #ifdef QCP_DEVICEPIXELRATIO_SUPPORTED
30331 scaledSize /=
mPixmap.devicePixelRatio();
30336 result = QRect(
topLeft, scaledSize);
30339 #ifdef QCP_DEVICEPIXELRATIO_SUPPORTED
30342 result = QRect(p1,
mPixmap.size());
30346 *flippedHorz = flipHorz;
30348 *flippedVert = flipVert;
30409 position(createPosition(QLatin1String(
"position"))),
30411 mStyle(tsCrosshair),
30414 mInterpolating(false)
30420 setPen(QPen(Qt::black));
30509 qDebug() << Q_FUNC_INFO <<
"graph isn't in same QCustomPlot instance as this item";
30554 double w =
mSize/2.0;
30561 if (
clipRect().intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect()))
30562 return qSqrt(qMin(
QCPVector2D(pos).distanceSquaredToLine(center+QPointF(-w, 0), center+QPointF(w, 0)),
30563 QCPVector2D(pos).distanceSquaredToLine(center+QPointF(0, -w), center+QPointF(0, w))));
30573 if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect()))
30577 double circleLine = w;
30578 double result = qAbs(centerDist-circleLine);
30582 if (centerDist <= circleLine)
30591 if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect()))
30593 QRectF rect = QRectF(center-QPointF(w, w), center+QPointF(w, w));
30594 bool filledRect =
mBrush.style() != Qt::NoBrush &&
mBrush.color().alpha() != 0;
30613 double w =
mSize/2.0;
30620 if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect()))
30622 painter->
drawLine(QLineF(center+QPointF(-w, 0), center+QPointF(w, 0)));
30623 painter->
drawLine(QLineF(center+QPointF(0, -w), center+QPointF(0, w)));
30629 if (center.y() > clip.top() && center.y() < clip.bottom())
30630 painter->
drawLine(QLineF(clip.left(), center.y(), clip.right(), center.y()));
30631 if (center.x() > clip.left() && center.x() < clip.right())
30632 painter->
drawLine(QLineF(center.x(), clip.top(), center.x(), clip.bottom()));
30637 if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect()))
30638 painter->drawEllipse(center, w, w);
30643 if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect()))
30644 painter->drawRect(QRectF(center-QPointF(w, w), center+QPointF(w, w)));
30672 if (mGraphKey <= first->key)
30687 if (!qFuzzyCompare(
double(it->key),
double(prevIt->key)))
30688 slope = (it->value-prevIt->value)/(it->key-prevIt->key);
30693 if (
mGraphKey < (prevIt->key+it->key)*0.5)
30706 qDebug() << Q_FUNC_INFO <<
"graph has no data";
30708 qDebug() << Q_FUNC_INFO <<
"graph not contained in QCustomPlot instance (anymore)";
30769 left(createPosition(QLatin1String(
"left"))),
30770 right(createPosition(QLatin1String(
"right"))),
30771 center(createAnchor(QLatin1String(
"center"), aiCenter)),
30773 mStyle(bsCalligraphic)
30778 setPen(QPen(Qt::black));
30848 QCPVector2D centerVec = (rightVec+leftVec)*0.5-lengthVec;
30858 return qSqrt(qMin(qMin(a, b), c));
30863 double a = p.
distanceSquaredToLine(centerVec-widthVec*0.75+lengthVec*0.15, centerVec+lengthVec*0.3);
30864 double b = p.
distanceSquaredToLine(centerVec-widthVec+lengthVec*0.7, centerVec-widthVec*0.75+lengthVec*0.15);
30865 double c = p.
distanceSquaredToLine(centerVec+widthVec*0.75+lengthVec*0.15, centerVec+lengthVec*0.3);
30866 double d = p.
distanceSquaredToLine(centerVec+widthVec+lengthVec*0.7, centerVec+widthVec*0.75+lengthVec*0.15);
30867 return qSqrt(qMin(qMin(a, b), qMin(c, d)));
30883 QCPVector2D centerVec = (rightVec+leftVec)*0.5-lengthVec;
30885 QPolygon boundingPoly;
30887 << (rightVec-lengthVec).toPoint() << (leftVec-lengthVec).toPoint();
30888 const int clipEnlarge = qCeil(
mainPen().widthF());
30889 QRect clip =
clipRect().adjusted(-clipEnlarge, -clipEnlarge, clipEnlarge, clipEnlarge);
30890 if (clip.intersects(boundingPoly.boundingRect()))
30897 painter->
drawLine((centerVec+widthVec).toPointF(), (centerVec-widthVec).toPointF());
30898 painter->
drawLine((centerVec+widthVec).toPointF(), (centerVec+widthVec+lengthVec).toPointF());
30899 painter->
drawLine((centerVec-widthVec).toPointF(), (centerVec-widthVec+lengthVec).toPointF());
30904 painter->setBrush(Qt::NoBrush);
30906 path.moveTo((centerVec+widthVec+lengthVec).toPointF());
30907 path.cubicTo((centerVec+widthVec).toPointF(), (centerVec+widthVec).toPointF(), centerVec.
toPointF());
30908 path.cubicTo((centerVec-widthVec).toPointF(), (centerVec-widthVec).toPointF(), (centerVec-widthVec+lengthVec).toPointF());
30909 painter->drawPath(path);
30914 painter->setBrush(Qt::NoBrush);
30916 path.moveTo((centerVec+widthVec+lengthVec).toPointF());
30917 path.cubicTo((centerVec+widthVec-lengthVec*0.8).toPointF(), (centerVec+0.4*widthVec+lengthVec).toPointF(), centerVec.
toPointF());
30918 path.cubicTo((centerVec-0.4*widthVec+lengthVec).toPointF(), (centerVec-widthVec-lengthVec*0.8).toPointF(), (centerVec-widthVec+lengthVec).toPointF());
30919 painter->drawPath(path);
30924 painter->
setPen(Qt::NoPen);
30927 path.moveTo((centerVec+widthVec+lengthVec).toPointF());
30929 path.cubicTo((centerVec+widthVec-lengthVec*0.8).toPointF(), (centerVec+0.4*widthVec+0.8*lengthVec).toPointF(), centerVec.
toPointF());
30930 path.cubicTo((centerVec-0.4*widthVec+0.8*lengthVec).toPointF(), (centerVec-widthVec-lengthVec*0.8).toPointF(), (centerVec-widthVec+lengthVec).toPointF());
30932 path.cubicTo((centerVec-widthVec-lengthVec*0.5).toPointF(), (centerVec-0.2*widthVec+1.2*lengthVec).toPointF(), (centerVec+lengthVec*0.2).toPointF());
30933 path.cubicTo((centerVec+0.2*widthVec+1.2*lengthVec).toPointF(), (centerVec+widthVec-lengthVec*0.5).toPointF(), (centerVec+widthVec+lengthVec).toPointF());
30935 painter->drawPath(path);
30952 QCPVector2D centerVec = (rightVec+leftVec)*0.5-lengthVec;
30959 qDebug() << Q_FUNC_INFO <<
"invalid anchorId" << anchorId;
31065 QCPLayerable(parent->parentPlot(), QString(), parent),
31068 mRangeZoomFactor(0.85),
31070 mAngularAxis(parent),
31072 mAngleReference(arAngularAxis),
31073 mSelectableParts(spAxis | spTickLabels | spAxisLabel),
31074 mSelectedParts(spNone),
31075 mBasePen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
31076 mSelectedBasePen(QPen(Qt::blue, 2)),
31080 mLabelFont(mParentPlot->font()),
31081 mSelectedLabelFont(QFont(mLabelFont.family(), mLabelFont.pointSize(), QFont::Bold)),
31082 mLabelColor(Qt::black),
31083 mSelectedLabelColor(Qt::blue),
31088 mTickLabelFont(mParentPlot->font()),
31089 mSelectedTickLabelFont(QFont(mTickLabelFont.family(), mTickLabelFont.pointSize(), QFont::Bold)),
31090 mTickLabelColor(Qt::black),
31091 mSelectedTickLabelColor(Qt::blue),
31092 mNumberPrecision(6),
31093 mNumberFormatChar(
'g'),
31094 mNumberBeautifulPowers(true),
31095 mNumberMultiplyCross(false),
31101 mSubTickLengthIn(2),
31102 mSubTickLengthOut(0),
31103 mTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
31104 mSelectedTickPen(QPen(Qt::blue, 2)),
31105 mSubTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
31106 mSelectedSubTickPen(QPen(Qt::blue, 2)),
31109 mRangeReversed(false),
31110 mScaleType(stLinear),
31114 mLabelPainter(mParentPlot)
31136 default: qDebug() << Q_FUNC_INFO <<
"invalid mode for polar axis";
break;
31148 result.append(QLatin1Char(
'b'));
31150 result.append(QLatin1Char(
'c'));
31337 if (alignment == Qt::AlignLeft)
31338 setRange(position, position+size);
31339 else if (alignment == Qt::AlignRight)
31340 setRange(position-size, position);
31342 setRange(position-size/2.0, position+size/2.0);
31431 qDebug() << Q_FUNC_INFO <<
"can not set 0 as axis ticker";
31554 if (formatCode.isEmpty())
31556 qDebug() << Q_FUNC_INFO <<
"Passed formatCode is empty";
31562 QString allowedFormatChars(QLatin1String(
"eEfgG"));
31563 if (allowedFormatChars.contains(formatCode.at(0)))
31568 qDebug() << Q_FUNC_INFO <<
"Invalid number format code (first char not in 'eEfgG'):" << formatCode;
31572 if (formatCode.length() < 2)
31582 qDebug() << Q_FUNC_INFO <<
"Invalid number format code (second char not 'b' or first char neither 'e' nor 'g'):" << formatCode;
31584 if (formatCode.length() < 3)
31590 if (formatCode.at(2) == QLatin1Char(
'c'))
31592 else if (formatCode.at(2) == QLatin1Char(
'd'))
31595 qDebug() << Q_FUNC_INFO <<
"Invalid number format code (third char neither 'c' nor 'd'):" << formatCode;
31945 qDebug() << Q_FUNC_INFO <<
"Center of scaling operation doesn't lie in same logarithmic sign domain as range:" << center;
31959 Q_UNUSED(onlyVisiblePlottables)
32023 return QPointF(
mCenter.x()+qCos(angleRad)*radiusPixel,
mCenter.y()+qSin(angleRad)*radiusPixel);
32038 else if (coord <= 0.0 && mRange.upper >= 0.0)
32104 details->setValue(part);
32117 if (selectionStateChanged)
32127 if (selectionStateChanged)
32155 if (event->buttons() & Qt::LeftButton)
32299 const QPointF axisVector(qCos(axisAngleRad), qSin(axisAngleRad));
32324 painter->
setPen(ticksPen);
32328 const QPointF tickPosition =
mCenter+axisVector*r;
32541 mBackgroundBrush(Qt::NoBrush),
32542 mBackgroundScaled(true),
32543 mBackgroundScaledMode(Qt::KeepAspectRatioByExpanding),
32547 mRangeZoomFactor(0.85),
32550 mAngleRad(mAngle/180.0*M_PI),
32551 mSelectableParts(spAxis | spTickLabels | spAxisLabel),
32552 mSelectedParts(spNone),
32553 mBasePen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
32554 mSelectedBasePen(QPen(Qt::blue, 2)),
32558 mLabelFont(mParentPlot->font()),
32559 mSelectedLabelFont(QFont(mLabelFont.family(), mLabelFont.pointSize(), QFont::Bold)),
32560 mLabelColor(Qt::black),
32561 mSelectedLabelColor(Qt::blue),
32566 mTickLabelFont(mParentPlot->font()),
32567 mSelectedTickLabelFont(QFont(mTickLabelFont.family(), mTickLabelFont.pointSize(), QFont::Bold)),
32568 mTickLabelColor(Qt::black),
32569 mSelectedTickLabelColor(Qt::blue),
32570 mNumberPrecision(6),
32571 mNumberFormatChar(
'g'),
32572 mNumberBeautifulPowers(true),
32573 mNumberMultiplyCross(false),
32579 mSubTickLengthIn(2),
32580 mSubTickLengthOut(0),
32581 mTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
32582 mSelectedTickPen(QPen(Qt::blue, 2)),
32583 mSubTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
32584 mSelectedSubTickPen(QPen(Qt::blue, 2)),
32587 mRangeReversed(false),
32593 mLabelPainter(parentPlot)
32602 fixedTicker->setTickStep(30);
32629 QList<QCPPolarAxisRadial*> radialAxesList =
radialAxes();
32630 for (
int i=0; i<radialAxesList.size(); ++i)
32640 default: qDebug() << Q_FUNC_INFO <<
"invalid mode for polar axis";
break;
32652 result.append(QLatin1Char(
'b'));
32654 result.append(QLatin1Char(
'c'));
32681 qDebug() << Q_FUNC_INFO <<
"Axis index out of bounds:" << index;
32730 qDebug() << Q_FUNC_INFO <<
"passed radial axis doesn't have this angular axis as parent angular axis";
32735 qDebug() << Q_FUNC_INFO <<
"passed axis is already owned by this angular axis";
32759 qDebug() << Q_FUNC_INFO <<
"Radial axis isn't associated with this angular axis:" <<
reinterpret_cast<quintptr
>(
radialAxis);
32829 bool haveRange =
false;
32830 for (
int i=0; i<
mGraphs.size(); ++i)
32832 if (!
mGraphs.at(i)->realVisibility() && onlyVisiblePlottables)
32835 bool currentFoundRange;
32836 if (
mGraphs.at(i)->keyAxis() ==
this)
32840 if (currentFoundRange)
32867 mRadialAxes.first()->pixelToCoord(pixelPos, angleCoord, radiusCoord);
32869 qDebug() << Q_FUNC_INFO <<
"no radial axis configured";
32879 return mRadialAxes.first()->coordToPixel(angleCoord, radiusCoord);
32882 qDebug() << Q_FUNC_INFO <<
"no radial axis configured";
32931 if (onlySelectable)
32940 qDebug() << Q_FUNC_INFO <<
"parent plot not defined";
32991 QList<QCPLayoutElement*> result;
33003 if (!
mGraphs.contains(graph))
33005 qDebug() << Q_FUNC_INFO <<
"graph not in list:" <<
reinterpret_cast<quintptr
>(graph);
33050 painter->
setPen(ticksPen);
33271 if (alignment == Qt::AlignLeft)
33273 else if (alignment == Qt::AlignRight)
33349 qDebug() << Q_FUNC_INFO <<
"can not set 0 as axis ticker";
33468 if (formatCode.isEmpty())
33470 qDebug() << Q_FUNC_INFO <<
"Passed formatCode is empty";
33476 QString allowedFormatChars(QLatin1String(
"eEfgG"));
33477 if (allowedFormatChars.contains(formatCode.at(0)))
33482 qDebug() << Q_FUNC_INFO <<
"Invalid number format code (first char not in 'eEfgG'):" << formatCode;
33486 if (formatCode.length() < 2)
33496 qDebug() << Q_FUNC_INFO <<
"Invalid number format code (second char not 'b' or first char neither 'e' nor 'g'):" << formatCode;
33498 if (formatCode.length() < 3)
33504 if (formatCode.at(2) == QLatin1Char(
'c'))
33506 else if (formatCode.at(2) == QLatin1Char(
'd'))
33509 qDebug() << Q_FUNC_INFO <<
"Invalid number format code (third char neither 'c' nor 'd'):" << formatCode;
33816 QPainterPath ellipsePath;
33825 QRegion originalClip = painter->clipRegion();
33826 painter->setClipRegion(clipCircle);
33839 painter->setClipRegion(originalClip);
33958 if (event->buttons() & Qt::LeftButton)
33988 bool doReplot =
false;
33995 double angleCoordStart, radiusCoordStart;
33996 double angleCoord, radiusCoord;
33997 pixelToCoord(startPos, angleCoordStart, radiusCoordStart);
33999 double diff = angleCoordStart - angleCoord;
34009 double angleCoordStart, radiusCoordStart;
34010 double angleCoord, radiusCoord;
34011 ax->
pixelToCoord(startPos, angleCoordStart, radiusCoordStart);
34012 ax->
pixelToCoord(event->pos(), angleCoord, radiusCoord);
34015 double diff = radiusCoordStart - radiusCoord;
34019 if (radiusCoord != 0)
34021 double diff = radiusCoordStart/radiusCoord;
34065 bool doReplot =
false;
34069 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
34070 const double delta =
event->delta();
34072 const double delta =
event->angleDelta().y();
34075 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
34076 const QPointF pos =
event->pos();
34078 const QPointF pos =
event->position();
34080 const double wheelSteps = delta/120.0;
34083 double angleCoord, radiusCoord;
34094 double angleCoord, radiusCoord;
34107 qDebug() << Q_FUNC_INFO <<
"plottable already added:" <<
reinterpret_cast<quintptr
>(graph);
34110 if (graph->
keyAxis() !=
this)
34112 qDebug() << Q_FUNC_INFO <<
"plottable not created with this as axis:" <<
reinterpret_cast<quintptr
>(graph);
34120 if (!graph->
layer())
34148 QCPLayerable(parentAxis->parentPlot(), QString(), parentAxis),
34150 mSubGridType(gtNone),
34151 mAntialiasedSubGrid(true),
34152 mAntialiasedZeroLine(true),
34153 mParentAxis(parentAxis)
34156 setParent(parentAxis);
34163 setRadialPen(QPen(QColor(200,200,200), 0, Qt::DotLine));
34257 if (!
mParentAxis) { qDebug() << Q_FUNC_INFO <<
"invalid parent axis";
return; }
34262 painter->setBrush(Qt::NoBrush);
34282 if (coords.isEmpty())
return;
34283 const bool drawZeroLine = zeroPen != Qt::NoPen;
34284 const double zeroLineEpsilon = qAbs(coords.last()-coords.first())*1e-6;
34287 for (
int i=0; i<coords.size(); ++i)
34289 const double r =
mRadialAxis->coordToRadius(coords.at(i));
34290 if (drawZeroLine && qAbs(coords.at(i)) < zeroLineEpsilon)
34293 painter->
setPen(zeroPen);
34294 painter->drawEllipse(center, r, r);
34299 painter->drawEllipse(center, r, r);
34306 if (ticksCosSin.isEmpty())
return;
34309 for (
int i=0; i<ticksCosSin.size(); ++i)
34310 painter->
drawLine(center, center+ticksCosSin.at(i)*radius);
34342 QRectF textRect = painter->fontMetrics().boundingRect(0, 0, 0, iconSize.height(), Qt::TextDontClip,
mPolarGraph->
name());
34343 QRectF iconRect(
mRect.topLeft(), iconSize);
34344 int textHeight = qMax(textRect.height(), iconSize.height());
34348 painter->setClipRect(iconRect, Qt::IntersectClip);
34355 painter->setBrush(Qt::NoBrush);
34356 int halfPen = qCeil(painter->pen().widthF()*0.5)+1;
34357 painter->setClipRect(
mOuterRect.adjusted(-halfPen, -halfPen, halfPen, halfPen));
34358 painter->drawRect(iconRect);
34365 QSize result(0, 0);
34367 QFontMetrics fontMetrics(
getFont());
34369 textRect = fontMetrics.boundingRect(0, 0, 0, iconSize.height(), Qt::TextDontClip,
mPolarGraph->
name());
34371 result.setHeight(qMax(textRect.height(), iconSize.height()));
34424 QCPLayerable(keyAxis->parentPlot(), QString(), keyAxis),
34427 mAntialiasedFill(true),
34428 mAntialiasedScatters(true),
34430 mBrush(Qt::NoBrush),
34433 mValueAxis(valueAxis),
34438 qDebug() << Q_FUNC_INFO <<
"Parent plot of keyAxis is not the same as that of valueAxis.";
34440 mKeyAxis->registerPolarGraph(
this);
34444 setPen(QPen(Qt::blue, 0));
34644 addData(keys, values, alreadySorted);
34671 if (keys.size() != values.size())
34672 qDebug() << Q_FUNC_INFO <<
"keys and values have different sizes:" << keys.size() << values.size();
34673 const int n = qMin(keys.size(), values.size());
34674 QVector<QCPGraphData> tempData(n);
34675 QVector<QCPGraphData>::iterator it = tempData.begin();
34676 const QVector<QCPGraphData>::iterator itEnd = tempData.end();
34678 while (it != itEnd)
34681 it->value = values[i];
34725 const QPointF point =
mValueAxis->coordToPixel(key, value);
34730 qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
34738 return mValueAxis->coordToPixel(key, value);
34741 qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
34750 mValueAxis->pixelToCoord(QPointF(x, y), key, value);
34753 qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
34761 mValueAxis->pixelToCoord(pixelPos, key, value);
34764 qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
34777 if (!
keyAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key axis";
return; }
34787 double center = (newRange.
lower+newRange.
upper)*0.5;
34799 if (!
keyAxis || !
valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return; }
34813 double center = (newRange.
lower+newRange.
upper)*0.5;
34832 qDebug() << Q_FUNC_INFO <<
"passed legend is null";
34837 qDebug() << Q_FUNC_INFO <<
"passed legend isn't in the same QCustomPlot as this plottable";
34861 qDebug() << Q_FUNC_INFO <<
"passed legend is null";
34867 for (
int i=0; i<legend->
itemCount(); ++i)
34871 if (pli->polarGraph() ==
this)
34873 removableItem = pli;
34900 if (
mKeyAxis->rect().contains(pos.toPoint()))
34923 return mDataContainer->valueRange(foundRange, inSignDomain, inKeyRange);
34937 if (!
mKeyAxis || !
mValueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return; }
34941 painter->setClipRegion(
mKeyAxis->exactClipRegion());
34943 QVector<QPointF> lines, scatters;
34946 QList<QCPDataRange> selectedSegments, unselectedSegments, allSegments;
34948 allSegments << unselectedSegments << selectedSegments;
34949 for (
int i=0; i<allSegments.size(); ++i)
34951 bool isSelectedSegment = i >= unselectedSegments.size();
34953 QCPDataRange lineDataRange = isSelectedSegment ? allSegments.at(i) : allSegments.at(i).
adjusted(-1, 1);
34957 #ifdef QCUSTOMPLOT_CHECK_DATA
34962 qDebug() << Q_FUNC_INFO <<
"Data point at" << it->key <<
"invalid." <<
"Plottable name:" <<
name();
34970 painter->setBrush(
mBrush);
34971 painter->
setPen(Qt::NoPen);
34982 painter->setBrush(Qt::NoBrush);
34991 if (!finalScatterStyle.
isNone())
35039 if (selectionStateChanged)
35040 *selectionStateChanged =
mSelection != selectionBefore;
35051 if (selectionStateChanged)
35052 *selectionStateChanged =
mSelection != selectionBefore;
35064 if (painter->pen().style() != Qt::NoPen && painter->pen().color().alpha() != 0)
35091 if (painter->brush().style() != Qt::NoBrush && painter->brush().color().alpha() != 0)
35092 painter->drawPolygon(QPolygonF(*lines));
35106 for (
int i=0; i<scatters.size(); ++i)
35107 style.
drawShape(painter, scatters.at(i).x(), scatters.at(i).y());
35113 if (
mBrush.style() != Qt::NoBrush)
35116 painter->fillRect(QRectF(rect.left(), rect.top()+rect.height()/2.0, rect.width(), rect.height()/3.0),
mBrush);
35123 painter->
drawLine(QLineF(rect.left(), rect.top()+rect.height()/2.0, rect.right()+5, rect.top()+rect.height()/2.0));
35133 scaledStyle.
setPixmap(scaledStyle.
pixmap().scaled(rect.size().toSize(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
35135 scaledStyle.
drawShape(painter, QRectF(rect).center());
35163 double minDistSqr = (std::numeric_limits<double>::max)();
35165 double posKeyMin, posKeyMax, dummy;
35168 if (posKeyMin > posKeyMax)
35169 qSwap(posKeyMin, posKeyMax);
35176 if (currentDistSqr < minDistSqr)
35178 minDistSqr = currentDistSqr;
35187 QVector<QPointF> lineData;
35190 for (
int i=0; i<lineData.size()-1; ++i)
35193 if (currentDistSqr < minDistSqr)
35194 minDistSqr = currentDistSqr;
35198 return qSqrt(minDistSqr);
35208 selectedSegments.clear();
35209 unselectedSegments.clear();
35229 painter->pen().style() == Qt::SolidLine &&
35234 bool lastIsNan =
false;
35235 const int lineDataSize = lineData.size();
35236 while (i < lineDataSize && (qIsNaN(lineData.at(i).y()) || qIsNaN(lineData.at(i).x())))
35239 while (i < lineDataSize)
35241 if (!qIsNaN(lineData.at(i).y()) && !qIsNaN(lineData.at(i).x()))
35244 painter->
drawLine(lineData.at(i-1), lineData.at(i));
35253 int segmentStart = 0;
35255 const int lineDataSize = lineData.size();
35256 while (i < lineDataSize)
35258 if (qIsNaN(lineData.at(i).y()) || qIsNaN(lineData.at(i).x()) || qIsInf(lineData.at(i).y()))
35260 painter->drawPolyline(lineData.constData()+segmentStart, i-segmentStart);
35261 segmentStart = i+1;
35266 painter->drawPolyline(lineData.constData()+segmentStart, lineDataSize-segmentStart);
35272 if (rangeRestriction.
isEmpty())
35280 if (!
keyAxis || !
valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return; }
35292 mDataContainer->limitIteratorsToDataRange(begin, end, rangeRestriction);
35318 if (!lines)
return;
35327 QVector<QCPGraphData> lineData;
35333 case lsNone: lines->clear();
break;
35342 if (!
keyAxis || !
valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return; }
35344 if (!scatters)
return;
35353 QVector<QCPGraphData>
data;
35356 scatters->resize(
data.size());
35357 for (
int i=0; i<
data.size(); ++i)
35359 if (!qIsNaN(
data.at(i).value))
35371 bool reversed =
mValueAxis->rangeReversed();
35372 const double clipMargin = range.
size()*0.05;
35373 const double upperClipValue = range.
upper + (reversed ? 0 : range.
size()*0.05+clipMargin);
35374 const double lowerClipValue = range.
lower - (reversed ? range.
size()*0.05+clipMargin : 0);
35375 const double maxKeySkip = qAsin(qSqrt(clipMargin*(clipMargin+2*range.
size()))/(range.
size()+clipMargin))/M_PI*
mKeyAxis->range().size();
35376 double skipBegin = 0;
35377 bool belowRange =
false;
35378 bool aboveRange =
false;
35382 if (it->value < lowerClipValue)
35386 aboveRange =
false;
35388 lineData->append(*(it-1));
35392 skipBegin = it->key;
35393 lineData->append(
QCPGraphData(it->key, lowerClipValue));
35396 if (it->key-skipBegin > maxKeySkip)
35398 skipBegin += maxKeySkip;
35399 lineData->append(
QCPGraphData(skipBegin, lowerClipValue));
35401 }
else if (it->value > upperClipValue)
35405 belowRange =
false;
35407 lineData->append(*(it-1));
35411 skipBegin = it->key;
35412 lineData->append(
QCPGraphData(it->key, upperClipValue));
35415 if (it->key-skipBegin > maxKeySkip)
35417 skipBegin += maxKeySkip;
35418 lineData->append(
QCPGraphData(skipBegin, upperClipValue));
35424 aboveRange =
false;
35426 lineData->append(*(it-1));
35430 belowRange =
false;
35432 lineData->append(*(it-1));
35434 lineData->append(*it);
35441 aboveRange =
false;
35443 lineData->append(*(it-1));
35447 belowRange =
false;
35449 lineData->append(*(it-1));
35455 scatterData->clear();
35458 bool reversed =
mValueAxis->rangeReversed();
35459 const double clipMargin = range.
size()*0.05;
35460 const double upperClipValue = range.
upper + (reversed ? 0 : clipMargin);
35461 const double lowerClipValue = range.
lower - (reversed ? clipMargin : 0);
35465 if (it->value > lowerClipValue && it->value < upperClipValue)
35466 scatterData->append(*it);
35483 QVector<QPointF> result;
35486 if (!
keyAxis || !
valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return result; }
35489 result.resize(
data.size());
35490 for (
int i=0; i<
data.size(); ++i)